X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Flin-lwp.c;h=56e7bb238718e1d102f88e6297865c2310d7afd3;hb=540af400154502df8054af624998b03f659f1043;hp=59de1180c8edeed2793d7f9ca734ac7abb76515d;hpb=3f07c44bc9f1a80bdf5b44f363a6d85a7e07f8aa;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/lin-lwp.c b/gdb/lin-lwp.c index 59de1180c8..56e7bb2387 100644 --- a/gdb/lin-lwp.c +++ b/gdb/lin-lwp.c @@ -1,5 +1,5 @@ /* Multi-threaded debugging support for Linux (LWP layer). - Copyright 2000 Free Software Foundation, Inc. + Copyright 2000, 2001 Free Software Foundation, Inc. This file is part of GDB. @@ -29,6 +29,7 @@ #include "gdbthread.h" #include "inferior.h" #include "target.h" +#include "regcache.h" #define DEBUG 1 @@ -62,7 +63,7 @@ extern const char *strsignal (int sig); cannot use it since GDB must work on older systems too. - When a traced, cloned process exits and is waited for by the - debugger, the kernel reassigns it to the origional parent and + debugger, the kernel reassigns it to the original parent and keeps it around as a "zombie". Somehow, the LinuxThreads library doesn't notice this, which leads to the "zombie problem": When debugged a multi-threaded process that spawns a lot of threads @@ -130,16 +131,16 @@ extern struct target_ops child_ops; /* Since we cannot wait (in lin_lwp_wait) for the initial process and any cloned processes with a single call to waitpid, we have to use - use the WNOHANG flag and call waitpid in a loop. To optimize + the WNOHANG flag and call waitpid in a loop. To optimize things a bit we use `sigsuspend' to wake us up when a process has something to report (it will send us a SIGCHLD if it has). To make this work we have to juggle with the signal mask. We save the - origional signal mask such that we can restore it before creating a + original signal mask such that we can restore it before creating a new process in order to avoid blocking certain signals in the inferior. We then block SIGCHLD during the waitpid/sigsuspend loop. */ -/* Origional signal mask. */ +/* Original signal mask. */ static sigset_t normal_mask; /* Signal mask for use with sigsuspend in lin_lwp_wait, initialized in @@ -164,7 +165,7 @@ init_lwp_list (void) for (lp = lwp_list; lp; lp = lpnext) { lpnext = lp->next; - free (lp); + xfree (lp); } lwp_list = NULL; @@ -222,7 +223,7 @@ delete_lwp (int pid) else lwp_list = lp->next; - free (lp); + xfree (lp); } /* Return a pointer to the structure describing the LWP corresponding @@ -268,7 +269,7 @@ restore_inferior_pid (void *arg) { int *saved_pid_ptr = arg; inferior_pid = *saved_pid_ptr; - free (arg); + xfree (arg); } static struct cleanup * @@ -282,7 +283,11 @@ save_inferior_pid (void) } -/* Implementation of the PREPARE_TO_PROCEED hook for the Linux LWP layer. */ +/* Implementation of the PREPARE_TO_PROCEED hook for the Linux LWP + layer. + + Note that this implementation is potentially redundant now that + default_prepare_to_proceed() has been added. */ int lin_lwp_prepare_to_proceed (void) @@ -438,10 +443,6 @@ lin_lwp_resume (int pid, int step, enum target_signal signo) { pid = GET_LWP (lp->pid); - /* Mark LWP as not stopped to prevent it from being continued by - resume_callback. */ - lp->stopped = 0; - /* Remember if we're stepping. */ lp->step = step; @@ -454,6 +455,10 @@ lin_lwp_resume (int pid, int step, enum target_signal signo) gdb_assert (signo == TARGET_SIGNAL_0); return; } + + /* Mark LWP as not stopped to prevent it from being continued by + resume_callback. */ + lp->stopped = 0; } if (resume_all) @@ -506,14 +511,19 @@ stop_wait_callback (struct lwp_info *lp, void *data) if (WIFEXITED (status) || WIFSIGNALED (status)) { gdb_assert (num_lwps > 1); - gdb_assert (! is_cloned (lp->pid)); - - gdb_assert (in_thread_list (lp->pid)); - if (lp->pid != inferior_pid) - delete_thread (lp->pid); - printf_unfiltered ("[%s exited]\n", - target_pid_to_str (lp->pid)); + if (in_thread_list (lp->pid)) + { + /* Core GDB cannot deal with us deleting the current + thread. */ + if (lp->pid != inferior_pid) + delete_thread (lp->pid); + printf_unfiltered ("[%s exited]\n", + target_pid_to_str (lp->pid)); + } +#if DEBUG + printf ("%s exited.\n", target_pid_to_str (lp->pid)); +#endif delete_lwp (lp->pid); return 0; } @@ -708,7 +718,7 @@ lin_lwp_wait (int pid, struct target_waitstatus *ourstatus) { if (in_thread_list (lp->pid)) { - /* Core GDB cannot deal with us deeting the current + /* Core GDB cannot deal with us deleting the current thread. */ if (lp->pid != inferior_pid) delete_thread (lp->pid); @@ -890,7 +900,7 @@ lin_lwp_mourn_inferior (void) trap_pid = 0; - /* Restore the origional signal mask. */ + /* Restore the original signal mask. */ sigprocmask (SIG_SETMASK, &normal_mask, NULL); sigemptyset (&blocked_mask); @@ -930,6 +940,7 @@ lin_lwp_store_registers (int regno) static int lin_lwp_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write, + struct mem_attrib *attrib, struct target_ops *target) { struct cleanup *old_chain = save_inferior_pid (); @@ -938,7 +949,7 @@ lin_lwp_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write, if (is_lwp (inferior_pid)) inferior_pid = GET_LWP (inferior_pid); - xfer = child_xfer_memory (memaddr, myaddr, len, write, target); + xfer = child_xfer_memory (memaddr, myaddr, len, write, attrib, target); do_cleanups (old_chain); return xfer; @@ -1016,7 +1027,7 @@ _initialize_lin_lwp (void) add_target (&lin_lwp_ops); thread_db_init (&lin_lwp_ops); - /* Save the origional signal mask. */ + /* Save the original signal mask. */ sigprocmask (SIG_SETMASK, NULL, &normal_mask); action.sa_handler = sigchld_handler;