From 28561a655942f8e2a70a3b64e867223a60aae7b1 Mon Sep 17 00:00:00 2001 From: Simon Marchi Date: Wed, 1 Dec 2021 09:40:02 -0500 Subject: [PATCH] gdb/remote.c: refactor pending fork status functions In preparation for a following patch, refactor a few things that I did find a bit awkward, and to make them a bit more reusable. - Pass an inferior to kill_new_fork_children instead of a pid. That allows iterating on only this inferior's threads and avoid further filtering on the thread's pid. - Change thread_pending_fork_status to return a non-nullptr value only if the thread does have a pending fork status. - Remove is_pending_fork_parent_thread, as one can just use thread_pending_fork_status and check for nullptr. - Replace is_pending_fork_parent with is_fork_status, which just returns if the given target_waitkind if a fork or a vfork. Push filtering on the pid to the callers, when it is necessary. Change-Id: I0764ccc684d40f054e39df6fa5458cc4c5d1cd7b --- gdb/remote.c | 115 ++++++++++++++++++++++++--------------------------- 1 file changed, 53 insertions(+), 62 deletions(-) diff --git a/gdb/remote.c b/gdb/remote.c index f78417b5de7..d70acdc26c0 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -776,7 +776,7 @@ public: /* Remote specific methods. */ void remote_btrace_maybe_reopen (); void remove_new_fork_children (threads_listing_context *context); - void kill_new_fork_children (int pid); + void kill_new_fork_children (inferior *inf); void discard_pending_stop_replies (struct inferior *inf); int stop_reply_queue_length (); @@ -5876,45 +5876,30 @@ remote_target::open_1 (const char *name, int from_tty, int extended_p) rs->wait_forever_enabled_p = 1; } -/* Determine if THREAD_PTID is a pending fork parent thread. ARG contains - the pid of the process that owns the threads we want to check, or - -1 if we want to check all threads. */ +/* Determine if WS represents a fork status. */ -static int -is_pending_fork_parent (const target_waitstatus &ws, int event_pid, - ptid_t thread_ptid) +static bool +is_fork_status (target_waitkind kind) { - if (ws.kind () == TARGET_WAITKIND_FORKED - || ws.kind () == TARGET_WAITKIND_VFORKED) - { - if (event_pid == -1 || event_pid == thread_ptid.pid ()) - return 1; - } - - return 0; + return (kind == TARGET_WAITKIND_FORKED + || kind == TARGET_WAITKIND_VFORKED); } -/* Return the thread's pending status used to determine whether the - thread is a fork parent stopped at a fork event. */ +/* Return THREAD's pending status if it is a pending fork parent, else + return nullptr. */ -static const target_waitstatus & +static const target_waitstatus * thread_pending_fork_status (struct thread_info *thread) { - if (thread->has_pending_waitstatus ()) - return thread->pending_waitstatus (); - else - return thread->pending_follow; -} + const target_waitstatus &ws + = (thread->has_pending_waitstatus () + ? thread->pending_waitstatus () + : thread->pending_follow); -/* Determine if THREAD is a pending fork parent thread. */ + if (!is_fork_status (ws.kind ())) + return nullptr; -static int -is_pending_fork_parent_thread (struct thread_info *thread) -{ - const target_waitstatus &ws = thread_pending_fork_status (thread); - int pid = -1; - - return is_pending_fork_parent (ws, pid, thread->ptid); + return &ws; } /* Detach the specified process. */ @@ -6828,7 +6813,7 @@ remote_target::commit_resumed () /* If a thread is the parent of an unfollowed fork, then we can't do a global wildcard, as that would resume the fork child. */ - if (is_pending_fork_parent_thread (tp)) + if (thread_pending_fork_status (tp) != nullptr) may_global_wildcard_vcont = false; } @@ -7303,17 +7288,18 @@ struct notif_client notif_client_stop = void remote_target::remove_new_fork_children (threads_listing_context *context) { - int pid = -1; struct notif_client *notif = ¬if_client_stop; /* For any threads stopped at a fork event, remove the corresponding fork child threads from the CONTEXT list. */ for (thread_info *thread : all_non_exited_threads (this)) { - const target_waitstatus &ws = thread_pending_fork_status (thread); + const target_waitstatus *ws = thread_pending_fork_status (thread); + + if (ws == nullptr) + continue; - if (is_pending_fork_parent (ws, pid, thread->ptid)) - context->remove_thread (ws.child_ptid ()); + context->remove_thread (ws->child_ptid ()); } /* Check for any pending fork events (not reported or processed yet) @@ -10066,45 +10052,48 @@ remote_target::getpkt_or_notif_sane (gdb::char_vector *buf, int forever, return getpkt_or_notif_sane_1 (buf, forever, 1, is_notif); } -/* Kill any new fork children of process PID that haven't been +/* Kill any new fork children of inferior INF that haven't been processed by follow_fork. */ void -remote_target::kill_new_fork_children (int pid) +remote_target::kill_new_fork_children (inferior *inf) { remote_state *rs = get_remote_state (); struct notif_client *notif = ¬if_client_stop; - /* Kill the fork child threads of any threads in process PID - that are stopped at a fork event. */ - for (thread_info *thread : all_non_exited_threads (this)) + /* Kill the fork child threads of any threads in inferior INF that are stopped + at a fork event. */ + for (thread_info *thread : inf->non_exited_threads ()) { - const target_waitstatus &ws = thread->pending_follow; + const target_waitstatus *ws = thread_pending_fork_status (thread); - if (is_pending_fork_parent (ws, pid, thread->ptid)) - { - int child_pid = ws.child_ptid ().pid (); - int res; + if (ws == nullptr) + continue; - res = remote_vkill (child_pid); - if (res != 0) - error (_("Can't kill fork child process %d"), child_pid); - } + int child_pid = ws->child_ptid ().pid (); + int res = remote_vkill (child_pid); + + if (res != 0) + error (_("Can't kill fork child process %d"), child_pid); } /* Check for any pending fork events (not reported or processed yet) - in process PID and kill those fork child threads as well. */ + in inferior INF and kill those fork child threads as well. */ remote_notif_get_pending_events (notif); for (auto &event : rs->stop_reply_queue) - if (is_pending_fork_parent (event->ws, pid, event->ptid)) - { - int child_pid = event->ws.child_ptid ().pid (); - int res; + { + if (event->ptid.pid () != inf->pid) + continue; - res = remote_vkill (child_pid); - if (res != 0) - error (_("Can't kill fork child process %d"), child_pid); - } + if (!is_fork_status (event->ws.kind ())) + continue; + + int child_pid = event->ws.child_ptid ().pid (); + int res = remote_vkill (child_pid); + + if (res != 0) + error (_("Can't kill fork child process %d"), child_pid); + } } @@ -10114,18 +10103,20 @@ void remote_target::kill () { int res = -1; - int pid = inferior_ptid.pid (); + inferior *inf = find_inferior_pid (this, inferior_ptid.pid ()); struct remote_state *rs = get_remote_state (); + gdb_assert (inf != nullptr); + if (packet_support (PACKET_vKill) != PACKET_DISABLE) { /* If we're stopped while forking and we haven't followed yet, kill the child task. We need to do this before killing the parent task because if this is a vfork then the parent will be sleeping. */ - kill_new_fork_children (pid); + kill_new_fork_children (inf); - res = remote_vkill (pid); + res = remote_vkill (inf->pid); if (res == 0) { target_mourn_inferior (inferior_ptid); -- 2.30.2