diff options
author | Michael Snyder <msnyder@vmware.com> | 2005-11-27 00:02:46 +0000 |
---|---|---|
committer | Michael Snyder <msnyder@vmware.com> | 2005-11-27 00:02:46 +0000 |
commit | 1d2d1dd46fb45402443192a14cd2e485596f242f (patch) | |
tree | a2c76d7c10b66809cb54c931bd8e01754fa4a25e | |
parent | b80f8a5de994430287506f85c58659584948628f (diff) | |
download | gdb-1d2d1dd46fb45402443192a14cd2e485596f242f.zip gdb-1d2d1dd46fb45402443192a14cd2e485596f242f.tar.gz gdb-1d2d1dd46fb45402443192a14cd2e485596f242f.tar.bz2 |
2005-11-26 Michael Snyder <msnyder@redhat.com>
* linux-nat.c (super_mourn_inferior): New function pointer.
(child_mourn_inferior): New method, overrides to_mourn_inferior.
Handles multiple forks.
(linux_target): Intercept to_mourn_inferior, save pointer to
parent method.
-rw-r--r-- | gdb/ChangeLog | 8 | ||||
-rw-r--r-- | gdb/linux-nat.c | 63 |
2 files changed, 66 insertions, 5 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index df28ca7..0c49ef3 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,13 @@ 2005-11-26 Michael Snyder <msnyder@redhat.com> + * linux-nat.c (super_mourn_inferior): New function pointer. + (child_mourn_inferior): New method, overrides to_mourn_inferior. + Handles multiple forks. + (linux_target): Intercept to_mourn_inferior, save pointer to + parent method. + +2005-11-26 Michael Snyder <msnyder@redhat.com> + * linux-fork.h: New file. * linux-nat.c: Include linux-fork.h, remove forward declarations. (kill_inferior): Loop over forks and PTRACE_KILL them all. diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c index 757b37e..ebba1b1 100644 --- a/gdb/linux-nat.c +++ b/gdb/linux-nat.c @@ -90,12 +90,18 @@ the use of the multi-threaded target. */ static struct target_ops *linux_ops; -/* The saved to_xfer_partial method, inherited from inf-ptrace.c. Called - by our to_xfer_partial. */ -static LONGEST (*super_xfer_partial) (struct target_ops *, enum target_object, - const char *, gdb_byte *, const gdb_byte *, +/* The saved to_xfer_partial method, inherited from inf-ptrace.c. + Called by our to_xfer_partial. */ +static LONGEST (*super_xfer_partial) (struct target_ops *, + enum target_object, + const char *, gdb_byte *, + const gdb_byte *, ULONGEST, LONGEST); +/* The saved to_mourn_inferior method, inherited from inf-ptrace.c. + Called by our to_mourn_inferior. */ +static void (*super_mourn_inferior) (void); + static int debug_linux_nat; static void show_debug_linux_nat (struct ui_file *file, int from_tty, @@ -1785,6 +1791,48 @@ resumed_callback (struct lwp_info *lp, void *data) return lp->resumed; } +/* Local mourn_inferior -- we need to override mourn_inferior + so that we can do something clever if one of several forks + has exited. */ + +static void +child_mourn_inferior (void) +{ + int status; + + if (fork_list && + fork_list->next == NULL && + ptid_equal (fork_list->ptid, inferior_ptid)) + { + /* Last fork -- delete from list and handle as solo process. */ + delete_fork (inferior_ptid); + } + + if (fork_list == NULL) + { + /* Normal case, no other forks available. */ + super_mourn_inferior (); + return; + } + + /* Multi-fork case. */ + /* Wait just one more time to collect the inferior's exit status. + Do not check whether this succeeds though, since we may be + dealing with a process that we attached to. Such a process will + only report its exit status to its origional parent. */ + waitpid (ptid_get_pid (inferior_ptid), &status, 0); + + /* OK, presumably inferior_ptid is the one who has exited. + We need to delete that one from the fork_list, and switch + to the next available fork. FIXME safety? */ + delete_fork (inferior_ptid); + inferior_ptid = fork_list[0].ptid; + printf_filtered ("[Switching to %s]\n", + target_pid_to_str (inferior_ptid)); + + /* Is that enough? Maybe infrun will take care of everything else... */ +} + /* We need to override child_wait to support attaching to cloned processes, since a normal wait (as done by the default version) ignores those processes. */ @@ -3257,6 +3305,9 @@ linux_target (void) super_xfer_partial = t->to_xfer_partial; t->to_xfer_partial = linux_xfer_partial; + super_mourn_inferior = t->to_mourn_inferior; + t->to_mourn_inferior = child_mourn_inferior; + linux_ops = t; return t; } @@ -3767,8 +3818,10 @@ restart_command (char *args, int from_tty) fork_load_infrun_state (newfp); registers_changed (); /* FIXME lose this. */ +#if 0 target_fetch_registers (-1); /* FIXME should not be necessary; fill_gregset should do it automatically. */ +#endif reinit_frame_cache (); stop_pc = read_pc (); select_frame (get_current_frame ()); @@ -3781,7 +3834,7 @@ restart_command (char *args, int from_tty) newfp->been_restarted = 1; printf_filtered ("Switching to %s\n", - target_pid_or_tid_to_str (inferior_ptid)); + target_pid_to_str (inferior_ptid)); print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC); } |