forked from Imagelibrary/binutils-gdb
gdbserver: Queue no-resumed event after thread exit
Normally, if the last resumed thread on the target exits, the server sends a no-resumed event to GDB. If however, GDB enables the GDB_THREAD_OPTION_EXIT option on a thread, and, that thread exits, the server sends a thread exit event for that thread instead. In all-stop RSP mode, since events can only be forwarded to GDB one at a time, and the whole target stops whenever an event is reported, GDB resumes the target again after getting a THREAD_EXITED event, and then the server finally reports back a no-resumed event if/when appropriate. For non-stop RSP though, events are asynchronous, and if the server sends a thread-exit event for the last resumed thread, the no-resumed event is never sent. This patch makes sure that in non-stop mode, the server queues a no-resumed event after the thread-exit event if it was the last resumed thread that exited. Without this, we'd see failures in step-over-thread-exit testcases added later in the series, like so: continue Continuing. - No unwaited-for children left. - (gdb) PASS: gdb.threads/step-over-thread-exit.exp: displaced-stepping=off: non-stop=on: target-non-stop=on: schedlock=off: ns_stop_all=1: continue stops when thread exits + FAIL: gdb.threads/step-over-thread-exit.exp: displaced-stepping=off: non-stop=on: target-non-stop=on: schedlock=off: ns_stop_all=1: continue stops when thread exits (timeout) (and other similar ones) Reviewed-By: Andrew Burgess <aburgess@redhat.com> Change-Id: I927d78b30f88236dbd5634b051a716f72420e7c7
This commit is contained in:
@@ -2972,7 +2972,6 @@ linux_process_target::wait_1 (ptid_t ptid, target_waitstatus *ourstatus,
|
||||
int report_to_gdb;
|
||||
int trace_event;
|
||||
int in_step_range;
|
||||
int any_resumed;
|
||||
|
||||
threads_debug_printf ("[%s]", target_pid_to_str (ptid).c_str ());
|
||||
|
||||
@@ -2986,23 +2985,7 @@ linux_process_target::wait_1 (ptid_t ptid, target_waitstatus *ourstatus,
|
||||
in_step_range = 0;
|
||||
ourstatus->set_ignore ();
|
||||
|
||||
auto status_pending_p_any = [&] (thread_info *thread)
|
||||
{
|
||||
return status_pending_p_callback (thread, minus_one_ptid);
|
||||
};
|
||||
|
||||
auto not_stopped = [&] (thread_info *thread)
|
||||
{
|
||||
return not_stopped_callback (thread, minus_one_ptid);
|
||||
};
|
||||
|
||||
/* Find a resumed LWP, if any. */
|
||||
if (find_thread (status_pending_p_any) != NULL)
|
||||
any_resumed = 1;
|
||||
else if (find_thread (not_stopped) != NULL)
|
||||
any_resumed = 1;
|
||||
else
|
||||
any_resumed = 0;
|
||||
bool was_any_resumed = any_resumed ();
|
||||
|
||||
if (step_over_bkpt == null_ptid)
|
||||
pid = wait_for_event (ptid, &w, options);
|
||||
@@ -3013,7 +2996,7 @@ linux_process_target::wait_1 (ptid_t ptid, target_waitstatus *ourstatus,
|
||||
pid = wait_for_event (step_over_bkpt, &w, options & ~WNOHANG);
|
||||
}
|
||||
|
||||
if (pid == 0 || (pid == -1 && !any_resumed))
|
||||
if (pid == 0 || (pid == -1 && !was_any_resumed))
|
||||
{
|
||||
gdb_assert (target_options & TARGET_WNOHANG);
|
||||
|
||||
@@ -6177,6 +6160,32 @@ linux_process_target::thread_stopped (thread_info *thread)
|
||||
return get_thread_lwp (thread)->stopped;
|
||||
}
|
||||
|
||||
bool
|
||||
linux_process_target::any_resumed ()
|
||||
{
|
||||
bool any_resumed;
|
||||
|
||||
auto status_pending_p_any = [&] (thread_info *thread)
|
||||
{
|
||||
return status_pending_p_callback (thread, minus_one_ptid);
|
||||
};
|
||||
|
||||
auto not_stopped = [&] (thread_info *thread)
|
||||
{
|
||||
return not_stopped_callback (thread, minus_one_ptid);
|
||||
};
|
||||
|
||||
/* Find a resumed LWP, if any. */
|
||||
if (find_thread (status_pending_p_any) != NULL)
|
||||
any_resumed = 1;
|
||||
else if (find_thread (not_stopped) != NULL)
|
||||
any_resumed = 1;
|
||||
else
|
||||
any_resumed = 0;
|
||||
|
||||
return any_resumed;
|
||||
}
|
||||
|
||||
/* This exposes stop-all-threads functionality to other modules. */
|
||||
|
||||
void
|
||||
|
||||
Reference in New Issue
Block a user