* linux-fork.c (linux_fork_detach): New.

* linux-fork.h (linux_fork_detach): Declare.
	* linux-nat.c (linux_child_follow_fork): When following the fork
	child, add the child inferior before possibly detaching from the
	parent.  Don't reinstall ourselves.
	(linux_nat_detach): Call linux_fork_detach if there are other
	forks to debug.
	* linux-thread-db.c (thread_db_detach): Don't call
	target_mourn_inferior.  Instead inline the necessary bits.
	* inf-ptrace.c (inf_ptrace_detach): Don't unpush the target if
	there are other inferiors to debug.
This commit is contained in:
Pedro Alves
2008-12-28 16:14:57 +00:00
parent 262452ec45
commit 7a7d33537f
6 changed files with 80 additions and 12 deletions

View File

@ -1,3 +1,17 @@
2008-12-28 Pedro Alves <pedro@codesourcery.com>
* linux-fork.c (linux_fork_detach): New.
* linux-fork.h (linux_fork_detach): Declare.
* linux-nat.c (linux_child_follow_fork): When following the fork
child, add the child inferior before possibly detaching from the
parent. Don't reinstall ourselves.
(linux_nat_detach): Call linux_fork_detach if there are other
forks to debug.
* linux-thread-db.c (thread_db_detach): Don't call
target_mourn_inferior. Instead inline the necessary bits.
* inf-ptrace.c (inf_ptrace_detach): Don't unpush the target if
there are other inferiors to debug.
2008-12-28 Jan Kratochvil <jan.kratochvil@redhat.com> 2008-12-28 Jan Kratochvil <jan.kratochvil@redhat.com>
Fix TYPE_HIGH_BOUND for TYPE_CODE_RANGE using arbitrary TYPE_NFIELDS in Fix TYPE_HIGH_BOUND for TYPE_CODE_RANGE using arbitrary TYPE_NFIELDS in

View File

@ -309,7 +309,9 @@ inf_ptrace_detach (struct target_ops *ops, char *args, int from_tty)
inferior_ptid = null_ptid; inferior_ptid = null_ptid;
detach_inferior (pid); detach_inferior (pid);
unpush_target (ops);
if (!have_inferiors ())
unpush_target (ops);
} }
/* Kill the inferior. */ /* Kill the inferior. */

View File

@ -387,6 +387,40 @@ linux_fork_mourn_inferior (void)
delete_fork (inferior_ptid); delete_fork (inferior_ptid);
} }
/* The current inferior_ptid is being detached, but there are other
viable forks to debug. Detach and delete it and context-switch to
the first available. */
extern void
linux_fork_detach (char *args, int from_tty)
{
/* OK, inferior_ptid is the one we are detaching from. We need to
delete it from the fork_list, and switch to the next available
fork. */
if (ptrace (PTRACE_DETACH, PIDGET (inferior_ptid), 0, 0))
error (_("Unable to detach %s"), target_pid_to_str (inferior_ptid));
delete_fork (inferior_ptid);
/* Delete process from GDB's inferior list. */
delete_inferior (ptid_get_pid (inferior_ptid));
/* There should still be a fork - if there's only one left,
delete_fork won't remove it, because we haven't updated
inferior_ptid yet. */
gdb_assert (fork_list);
fork_load_infrun_state (fork_list);
if (from_tty)
printf_filtered (_("[Switching to %s]\n"),
target_pid_to_str (inferior_ptid));
/* If there's only one fork, switch back to non-fork mode. */
if (fork_list->next == NULL)
delete_fork (inferior_ptid);
}
/* Fork list <-> user interface. */ /* Fork list <-> user interface. */
static void static void

View File

@ -23,6 +23,7 @@ extern struct fork_info *find_fork_pid (pid_t);
extern void fork_save_infrun_state (struct fork_info *, int); extern void fork_save_infrun_state (struct fork_info *, int);
extern void linux_fork_killall (void); extern void linux_fork_killall (void);
extern void linux_fork_mourn_inferior (void); extern void linux_fork_mourn_inferior (void);
extern void linux_fork_detach (char *, int);
extern int forks_exist_p (void); extern int forks_exist_p (void);
struct fork_info *fork_list; struct fork_info *fork_list;

View File

@ -826,6 +826,11 @@ linux_child_follow_fork (struct target_ops *ops, int follow_child)
child_pid); child_pid);
} }
/* Add the new inferior first, so that the target_detach below
doesn't unpush the target. */
add_inferior (child_pid);
/* If we're vforking, we may want to hold on to the parent until /* If we're vforking, we may want to hold on to the parent until
the child exits or execs. At exec time we can remove the old the child exits or execs. At exec time we can remove the old
breakpoints from the parent and detach it; at exit time we breakpoints from the parent and detach it; at exit time we
@ -868,12 +873,7 @@ linux_child_follow_fork (struct target_ops *ops, int follow_child)
target_detach (NULL, 0); target_detach (NULL, 0);
inferior_ptid = ptid_build (child_pid, child_pid, 0); inferior_ptid = ptid_build (child_pid, child_pid, 0);
add_inferior (child_pid);
/* Reinstall ourselves, since we might have been removed in
target_detach (which does other necessary cleanup). */
push_target (ops);
linux_nat_switch_fork (inferior_ptid); linux_nat_switch_fork (inferior_ptid);
check_for_thread_db (); check_for_thread_db ();
@ -1621,12 +1621,24 @@ linux_nat_detach (struct target_ops *ops, char *args, int from_tty)
/* Destroy LWP info; it's no longer valid. */ /* Destroy LWP info; it's no longer valid. */
init_lwp_list (); init_lwp_list ();
pid = GET_PID (inferior_ptid); pid = ptid_get_pid (inferior_ptid);
inferior_ptid = pid_to_ptid (pid);
linux_ops->to_detach (ops, args, from_tty);
if (target_can_async_p ()) if (target_can_async_p ())
drain_queued_events (pid); drain_queued_events (pid);
if (forks_exist_p ())
{
/* Multi-fork case. The current inferior_ptid is being detached
from, but there are other viable forks to debug. Detach from
the current fork, and context-switch to the first
available. */
linux_fork_detach (args, from_tty);
if (non_stop && target_can_async_p ())
target_async (inferior_event_handler, 0);
}
else
linux_ops->to_detach (ops, args, from_tty);
} }
/* Resume LP. */ /* Resume LP. */

View File

@ -784,10 +784,15 @@ thread_db_detach (struct target_ops *ops, char *args, int from_tty)
{ {
disable_thread_event_reporting (); disable_thread_event_reporting ();
target_beneath->to_detach (target_beneath, args, from_tty); /* Forget about the child's process ID. We shouldn't need it
anymore. */
proc_handle.pid = 0;
/* Should this be done by detach_command? */ /* Detach thread_db target ops. */
target_mourn_inferior (); unpush_target (&thread_db_ops);
using_thread_db = 0;
target_beneath->to_detach (target_beneath, args, from_tty);
} }
/* Check if PID is currently stopped at the location of a thread event /* Check if PID is currently stopped at the location of a thread event