static void linux_kill_one_process (struct inferior_list_entry *entry) { struct thread_info *thread = (struct thread_info *) entry; struct process_info *process = get_thread_process (thread); int wstat; do { ptrace (PTRACE_KILL, pid_of (process), 0, 0); /* Make sure it died. The loop is most likely unnecessary. */ wstat = linux_wait_for_event (thread); } while (WIFSTOPPED (wstat)); }
static void linux_kill (void) { struct thread_info *thread = (struct thread_info *) all_threads.head; struct process_info *process = get_thread_process (thread); int wstat; for_each_inferior (&all_threads, linux_kill_one_process); /* See the comment in linux_kill_one_process. We did not kill the first thread in the list, so do so now. */ do { ptrace (PTRACE_KILL, pid_of (process), 0, 0); /* Make sure it died. The loop is most likely unnecessary. */ wstat = linux_wait_for_event (thread); } while (WIFSTOPPED (wstat)); }
static void wait_for_sigstop (struct inferior_list_entry *entry) { struct process_info *process = (struct process_info *) entry; struct thread_info *saved_inferior, *thread; int wstat; unsigned long saved_tid; if (process->stopped) return; saved_inferior = current_inferior; saved_tid = ((struct inferior_list_entry *) saved_inferior)->id; thread = (struct thread_info *) find_inferior_id (&all_threads, process->tid); wstat = linux_wait_for_event (thread); /* If we stopped with a non-SIGSTOP signal, save it for later and record the pending SIGSTOP. If the process exited, just return. */ if (WIFSTOPPED (wstat) && WSTOPSIG (wstat) != SIGSTOP) { if (debug_threads) fprintf (stderr, "Stopped with non-sigstop signal\n"); process->status_pending_p = 1; process->status_pending = wstat; process->stop_expected = 1; } if (linux_thread_alive (saved_tid)) current_inferior = saved_inferior; else { if (debug_threads) fprintf (stderr, "Previously current thread died.\n"); /* Set a valid thread as current. */ set_desired_inferior (0); } }
static void linux_kill_one_process (struct inferior_list_entry *entry) { struct thread_info *thread = (struct thread_info *) entry; struct process_info *process = get_thread_process (thread); int wstat; /* We avoid killing the first thread here, because of a Linux kernel (at least 2.6.0-test7 through 2.6.8-rc4) bug; if we kill the parent before the children get a chance to be reaped, it will remain a zombie forever. */ if (entry == all_threads.head) return; do { ptrace (PTRACE_KILL, pid_of (process), 0, 0); /* Make sure it died. The loop is most likely unnecessary. */ wstat = linux_wait_for_event (thread); } while (WIFSTOPPED (wstat)); }
static unsigned char linux_wait (char *status) { int w; struct thread_info *child = NULL; retry: /* If we were only supposed to resume one thread, only wait for that thread - if it's still alive. If it died, however - which can happen if we're coming from the thread death case below - then we need to make sure we restart the other threads. We could pick a thread at random or restart all; restarting all is less arbitrary. */ if (cont_thread != 0 && cont_thread != -1) { child = (struct thread_info *) find_inferior_id (&all_threads, cont_thread); /* No stepping, no signal - unless one is pending already, of course. */ if (child == NULL) { struct thread_resume resume_info; resume_info.thread = -1; resume_info.step = resume_info.sig = resume_info.leave_stopped = 0; linux_resume (&resume_info); } } enable_async_io (); unblock_async_io (); w = linux_wait_for_event (child); stop_all_processes (); disable_async_io (); /* If we are waiting for a particular child, and it exited, linux_wait_for_event will return its exit status. Similarly if the last child exited. If this is not the last child, however, do not report it as exited until there is a 'thread exited' response available in the remote protocol. Instead, just wait for another event. This should be safe, because if the thread crashed we will already have reported the termination signal to GDB; that should stop any in-progress stepping operations, etc. Report the exit status of the last thread to exit. This matches LinuxThreads' behavior. */ if (all_threads.head == all_threads.tail) { if (WIFEXITED (w)) { fprintf (stderr, "\nChild exited with retcode = %x \n", WEXITSTATUS (w)); *status = 'W'; clear_inferiors (); free (all_processes.head); all_processes.head = all_processes.tail = NULL; return ((unsigned char) WEXITSTATUS (w)); } else if (!WIFSTOPPED (w)) { fprintf (stderr, "\nChild terminated with signal = %x \n", WTERMSIG (w)); *status = 'X'; clear_inferiors (); free (all_processes.head); all_processes.head = all_processes.tail = NULL; return ((unsigned char) WTERMSIG (w)); } } else { if (!WIFSTOPPED (w)) goto retry; } *status = 'T'; return ((unsigned char) WSTOPSIG (w)); }