forked from Imagelibrary/binutils-gdb
Implement GDB_THREAD_OPTION_EXIT support for native Linux
This implements support for the new GDB_THREAD_OPTION_EXIT thread option for native Linux. Reviewed-By: Andrew Burgess <aburgess@redhat.com> Change-Id: Ia69fc0b9b96f9af7de7cefc1ddb1fba9bbb0bb90 Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=27338
This commit is contained in:
@@ -268,6 +268,18 @@ pending_status_str (lwp_info *lp)
|
|||||||
return status_to_str (lp->status);
|
return status_to_str (lp->status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return true if we should report exit events for LP. */
|
||||||
|
|
||||||
|
static bool
|
||||||
|
report_exit_events_for (lwp_info *lp)
|
||||||
|
{
|
||||||
|
thread_info *thr = linux_target->find_thread (lp->ptid);
|
||||||
|
gdb_assert (thr != nullptr);
|
||||||
|
|
||||||
|
return (report_thread_events
|
||||||
|
|| (thr->thread_options () & GDB_THREAD_OPTION_EXIT) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* LWP accessors. */
|
/* LWP accessors. */
|
||||||
|
|
||||||
@@ -2148,8 +2160,7 @@ wait_lwp (struct lwp_info *lp)
|
|||||||
/* Check if the thread has exited. */
|
/* Check if the thread has exited. */
|
||||||
if (WIFEXITED (status) || WIFSIGNALED (status))
|
if (WIFEXITED (status) || WIFSIGNALED (status))
|
||||||
{
|
{
|
||||||
if (report_thread_events
|
if (report_exit_events_for (lp) || is_leader (lp))
|
||||||
|| lp->ptid.pid () == lp->ptid.lwp ())
|
|
||||||
{
|
{
|
||||||
linux_nat_debug_printf ("LWP %d exited.", lp->ptid.pid ());
|
linux_nat_debug_printf ("LWP %d exited.", lp->ptid.pid ());
|
||||||
|
|
||||||
@@ -2932,7 +2943,7 @@ linux_nat_filter_event (int lwpid, int status)
|
|||||||
/* Check if the thread has exited. */
|
/* Check if the thread has exited. */
|
||||||
if (WIFEXITED (status) || WIFSIGNALED (status))
|
if (WIFEXITED (status) || WIFSIGNALED (status))
|
||||||
{
|
{
|
||||||
if (!report_thread_events && !is_leader (lp))
|
if (!report_exit_events_for (lp) && !is_leader (lp))
|
||||||
{
|
{
|
||||||
linux_nat_debug_printf ("%s exited.",
|
linux_nat_debug_printf ("%s exited.",
|
||||||
lp->ptid.to_string ().c_str ());
|
lp->ptid.to_string ().c_str ());
|
||||||
@@ -3142,10 +3153,11 @@ check_zombie_leaders (void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convenience function that is called when the kernel reports an exit
|
/* Convenience function that is called when we're about to return an
|
||||||
event. This decides whether to report the event to GDB as a
|
event to the core. If the event is an exit or signalled event,
|
||||||
process exit event, a thread exit event, or to suppress the
|
then this decides whether to report it as process-wide event, as a
|
||||||
event. */
|
thread exit event, or to suppress it. All other event kinds are
|
||||||
|
passed through unmodified. */
|
||||||
|
|
||||||
static ptid_t
|
static ptid_t
|
||||||
filter_exit_event (struct lwp_info *event_child,
|
filter_exit_event (struct lwp_info *event_child,
|
||||||
@@ -3153,9 +3165,17 @@ filter_exit_event (struct lwp_info *event_child,
|
|||||||
{
|
{
|
||||||
ptid_t ptid = event_child->ptid;
|
ptid_t ptid = event_child->ptid;
|
||||||
|
|
||||||
|
/* Note we must filter TARGET_WAITKIND_SIGNALLED as well, otherwise
|
||||||
|
if a non-leader thread exits with a signal, we'd report it to the
|
||||||
|
core which would interpret it as the whole-process exiting.
|
||||||
|
There is no TARGET_WAITKIND_THREAD_SIGNALLED event kind. */
|
||||||
|
if (ourstatus->kind () != TARGET_WAITKIND_EXITED
|
||||||
|
&& ourstatus->kind () != TARGET_WAITKIND_SIGNALLED)
|
||||||
|
return ptid;
|
||||||
|
|
||||||
if (!is_leader (event_child))
|
if (!is_leader (event_child))
|
||||||
{
|
{
|
||||||
if (report_thread_events)
|
if (report_exit_events_for (event_child))
|
||||||
{
|
{
|
||||||
ourstatus->set_thread_exited (0);
|
ourstatus->set_thread_exited (0);
|
||||||
/* Delete lwp, but not thread_info, infrun will need it to
|
/* Delete lwp, but not thread_info, infrun will need it to
|
||||||
@@ -3388,10 +3408,7 @@ linux_nat_wait_1 (ptid_t ptid, struct target_waitstatus *ourstatus,
|
|||||||
else
|
else
|
||||||
lp->core = linux_common_core_of_thread (lp->ptid);
|
lp->core = linux_common_core_of_thread (lp->ptid);
|
||||||
|
|
||||||
if (ourstatus->kind () == TARGET_WAITKIND_EXITED)
|
return filter_exit_event (lp, ourstatus);
|
||||||
return filter_exit_event (lp, ourstatus);
|
|
||||||
|
|
||||||
return lp->ptid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Resume LWPs that are currently stopped without any pending status
|
/* Resume LWPs that are currently stopped without any pending status
|
||||||
@@ -4513,7 +4530,8 @@ linux_nat_target::thread_events (int enable)
|
|||||||
bool
|
bool
|
||||||
linux_nat_target::supports_set_thread_options (gdb_thread_options options)
|
linux_nat_target::supports_set_thread_options (gdb_thread_options options)
|
||||||
{
|
{
|
||||||
constexpr gdb_thread_options supported_options = GDB_THREAD_OPTION_CLONE;
|
constexpr gdb_thread_options supported_options
|
||||||
|
= GDB_THREAD_OPTION_CLONE | GDB_THREAD_OPTION_EXIT;
|
||||||
return ((options & supported_options) == options);
|
return ((options & supported_options) == options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user