-/* 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 (! forks_exist_p ())
- {
- /* Normal case, no other forks available. */
- super_mourn_inferior ();
- return;
- }
- else
- {
- /* Multi-fork case. The current inferior_ptid has exited, but
- there are other viable forks to debug. Delete the exiting
- one and context-switch to the first available. */
- linux_fork_mourn_inferior ();
- }
-}
-
-/* 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. */
-
-/* Wait for child PTID to do something. Return id of the child,
- minus_one_ptid in case of error; store status into *OURSTATUS. */
-
-ptid_t
-child_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
-{
- int save_errno;
- int status;
- pid_t pid;
-
- ourstatus->kind = TARGET_WAITKIND_IGNORE;
-
- do
- {
- set_sigint_trap (); /* Causes SIGINT to be passed on to the
- attached process. */
- set_sigio_trap ();
-
- pid = my_waitpid (GET_PID (ptid), &status, 0);
- if (pid == -1 && errno == ECHILD)
- /* Try again with __WCLONE to check cloned processes. */
- pid = my_waitpid (GET_PID (ptid), &status, __WCLONE);
-
- if (debug_linux_nat)
- {
- fprintf_unfiltered (gdb_stdlog,
- "CW: waitpid %ld received %s\n",
- (long) pid, status_to_str (status));
- }
-
- save_errno = errno;
-
- /* Make sure we don't report an event for the exit of the
- original program, if we've detached from it. */
- if (pid != -1 && !WIFSTOPPED (status) && pid != GET_PID (inferior_ptid))
- {
- pid = -1;
- save_errno = EINTR;
- }
-
- /* Check for stop events reported by a process we didn't already
- know about - in this case, anything other than inferior_ptid.
-
- If we're expecting to receive stopped processes after fork,
- vfork, and clone events, then we'll just add the new one to
- our list and go back to waiting for the event to be reported
- - the stopped process might be returned from waitpid before
- or after the event is. If we want to handle debugging of
- CLONE_PTRACE processes we need to do more here, i.e. switch
- to multi-threaded mode. */
- if (pid != -1 && WIFSTOPPED (status) && WSTOPSIG (status) == SIGSTOP
- && pid != GET_PID (inferior_ptid))
- {
- linux_record_stopped_pid (pid);
- pid = -1;
- save_errno = EINTR;
- }
-
- /* Handle GNU/Linux's extended waitstatus for trace events. */
- if (pid != -1 && WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP
- && status >> 16 != 0)
- {
- linux_handle_extended_wait (pid, status, ourstatus);
-
- /* If we see a clone event, detach the child, and don't
- report the event. It would be nice to offer some way to
- switch into a non-thread-db based threaded mode at this
- point. */
- if (ourstatus->kind == TARGET_WAITKIND_SPURIOUS)
- {
- ptrace (PTRACE_DETACH, ourstatus->value.related_pid, 0, 0);
- ourstatus->kind = TARGET_WAITKIND_IGNORE;
- ptrace (PTRACE_CONT, pid, 0, 0);
- pid = -1;
- save_errno = EINTR;
- }
- }
-
- clear_sigio_trap ();
- clear_sigint_trap ();
- }
- while (pid == -1 && save_errno == EINTR);
-
- if (pid == -1)
- {
- warning (_("Child process unexpectedly missing: %s"),
- safe_strerror (errno));
-
- /* Claim it exited with unknown signal. */
- ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
- ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
- return minus_one_ptid;
- }
-
- if (ourstatus->kind == TARGET_WAITKIND_IGNORE)
- store_waitstatus (ourstatus, status);
-
- return pid_to_ptid (pid);
-}
-