mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-01-06 12:09:26 +08:00
fbsd-nat: Stop a process if it is running before killing it.
In addition, detach from any child processes implicitly attached to by the kernel due to fork following that have not yet been processed by GDB's core.
This commit is contained in:
parent
57c28d45f9
commit
fdeef5e428
@ -1140,6 +1140,31 @@ fbsd_is_child_pending (pid_t pid)
|
||||
return null_ptid;
|
||||
}
|
||||
|
||||
/* Wait for a child of a fork to report its stop. Returns the PTID of
|
||||
the new child process. */
|
||||
|
||||
static ptid_t
|
||||
fbsd_wait_for_fork_child (pid_t pid)
|
||||
{
|
||||
ptid_t ptid = fbsd_is_child_pending (pid);
|
||||
if (ptid != null_ptid)
|
||||
return ptid;
|
||||
|
||||
int status;
|
||||
pid_t wpid = waitpid (pid, &status, 0);
|
||||
if (wpid == -1)
|
||||
perror_with_name (("waitpid"));
|
||||
|
||||
gdb_assert (wpid == pid);
|
||||
|
||||
struct ptrace_lwpinfo pl;
|
||||
if (ptrace (PT_LWPINFO, wpid, (caddr_t) &pl, sizeof pl) == -1)
|
||||
perror_with_name (("ptrace (PT_LWPINFO)"));
|
||||
|
||||
gdb_assert (pl.pl_flags & PL_FLAG_CHILD);
|
||||
return ptid_t (wpid, pl.pl_lwpid);
|
||||
}
|
||||
|
||||
#ifndef PTRACE_VFORK
|
||||
/* Record a pending vfork done event. */
|
||||
|
||||
@ -1447,23 +1472,7 @@ fbsd_nat_target::wait_1 (ptid_t ptid, struct target_waitstatus *ourstatus,
|
||||
#endif
|
||||
|
||||
/* Make sure the other end of the fork is stopped too. */
|
||||
child_ptid = fbsd_is_child_pending (child);
|
||||
if (child_ptid == null_ptid)
|
||||
{
|
||||
int status;
|
||||
|
||||
pid = waitpid (child, &status, 0);
|
||||
if (pid == -1)
|
||||
perror_with_name (("waitpid"));
|
||||
|
||||
gdb_assert (pid == child);
|
||||
|
||||
if (ptrace (PT_LWPINFO, child, (caddr_t) &pl, sizeof pl) == -1)
|
||||
perror_with_name (("ptrace (PT_LWPINFO)"));
|
||||
|
||||
gdb_assert (pl.pl_flags & PL_FLAG_CHILD);
|
||||
child_ptid = ptid_t (child, pl.pl_lwpid);
|
||||
}
|
||||
child_ptid = fbsd_wait_for_fork_child (child);
|
||||
|
||||
/* Enable additional events on the child process. */
|
||||
fbsd_enable_proc_events (child_ptid.pid ());
|
||||
@ -2105,6 +2114,56 @@ fbsd_nat_target::detach (inferior *inf, int from_tty)
|
||||
detach_success (inf);
|
||||
}
|
||||
|
||||
/* Implement the "kill" target method. */
|
||||
|
||||
void
|
||||
fbsd_nat_target::kill ()
|
||||
{
|
||||
pid_t pid = inferior_ptid.pid ();
|
||||
if (pid == 0)
|
||||
return;
|
||||
|
||||
inferior *inf = current_inferior ();
|
||||
stop_process (inf);
|
||||
|
||||
if (detach_fork_children (inf)) {
|
||||
/* No need to kill now. */
|
||||
target_mourn_inferior (inferior_ptid);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef TDP_RFPPWAIT
|
||||
/* If there are any threads that have forked a new child but not yet
|
||||
reported it because other threads reported events first, detach
|
||||
from the children before killing the parent. */
|
||||
auto lambda = [] (const struct ptrace_lwpinfo &pl)
|
||||
{
|
||||
if (pl.pl_flags & PL_FLAG_FORKED)
|
||||
{
|
||||
pid_t child = pl.pl_child_pid;
|
||||
|
||||
/* If the child hasn't reported its stop yet, wait for it to
|
||||
stop. */
|
||||
fbsd_wait_for_fork_child (child);
|
||||
|
||||
/* Detach from the child. */
|
||||
(void) ptrace (PT_DETACH, child, (caddr_t) 1, 0);
|
||||
}
|
||||
return false;
|
||||
};
|
||||
iterate_other_ptrace_events (pid, gdb::make_function_view (lambda));
|
||||
#endif
|
||||
|
||||
if (ptrace (PT_KILL, pid, NULL, 0) == -1)
|
||||
perror_with_name (("ptrace (PT_KILL)"));
|
||||
|
||||
int status;
|
||||
waitpid (pid, &status, 0);
|
||||
|
||||
target_mourn_inferior (inferior_ptid);
|
||||
}
|
||||
|
||||
void
|
||||
fbsd_nat_target::mourn_inferior ()
|
||||
{
|
||||
|
@ -83,6 +83,8 @@ class fbsd_nat_target : public inf_ptrace_target
|
||||
|
||||
void detach (inferior *, int) override;
|
||||
|
||||
void kill () override;
|
||||
|
||||
void mourn_inferior () override;
|
||||
|
||||
void resume (ptid_t, int, enum gdb_signal) override;
|
||||
|
Loading…
Reference in New Issue
Block a user