[PATCH v2 3/3] PR remote/19496, timeout in forking-threads-plus-bkpt
Don Breazeal
donb@codesourcery.com
Thu Feb 11 00:28:00 GMT 2016
On 2/1/2016 12:09 PM, Pedro Alves wrote:
> On 02/01/2016 07:29 PM, Don Breazeal wrote:
>> On 2/1/2016 4:05 AM, Pedro Alves wrote:
>
>> Hi Pedro,
---snip---
>> A fork event was reported to GDB before GDB knew about the parent thread,
>> followed immediately by a breakpoint event in a different thread. The
>> parent thread was subsequently added via remote_notice_new_inferior in
>> process_stop_reply, but when the thread was added the thread_info.state
>> was set to THREAD_STOPPED. The fork event was then handled correctly,
>> but when the fork parent was resumed via a call to keep_going, the state
>> was unchanged.
>
> Since this is non-stop, then it sounds to me like the bug is that the
> thread should have been added in THREAD_RUNNING state.
>
> Consider that infrun may be pulling target events out of the target_ops
> backend into its own event queue, but, not process them immediately.
>
> E.g., infrun may be stopping all threads temporarily for a step-over-breakpoint
> operation for thread A (stop_all_threads). The waitstatus of all threads
> is thus left pending in the thread structure (save_status), including the
> fork event of thread B. Right at this point, if the user
> does "info threads", that should show thread B (the fork parent) running,
> not stopped, even if internally, gdb is holding it paused for a little bit.
>
Hi Pedro,
Here is a new patch that adds the threads with the state set to
THREAD_RUNNING for fork events.
Thanks!
--Don
This patch addresses a failure in
gdb.threads/forking-threads-plus-breakpoint.exp:
FAIL: gdb.threads/forking-threads-plus-breakpoint.exp: cond_bp_target=1:
detach_on_fork=on: inferior 1 exited (timeout)
Cause:
A fork event was reported to GDB before GDB knew about the parent thread,
followed immediately by a breakpoint event in a different thread. The
parent thread was subsequently added via remote_notice_new_inferior in
process_stop_reply, but when the thread was added the thread_info.state
was set to THREAD_STOPPED. The fork event was then handled correctly,
but when the fork parent was resumed via a call to keep_going, the state
was unchanged.
The breakpoint event was then handled, which caused all the non-breakpoint
threads to be stopped. When the breakpoint thread was resumed, all the
non-breakpoint threads were resumed via infrun.c:restart_threads. Our old
fork parent wasn't restarted, because it still had thread_info.state set to
THREAD_STOPPED. Ultimately the program under debug hung waiting for a
pthread_join while the old fork parent was stopped forever by GDB.
Fix:
Make sure to add the fork parent thread in the THREAD_RUNNING state by
calling remote_notice_new_inferior with RUNNING set to 1 when processing
a fork stop reply.
Tested on x86_64 Linux and Nios II Linux target with x86 Linux host.
gdb/ChangeLog:
2016-02-10 Don Breazeal <donb@codesourcery.com>
* remote.c (process_stop_reply): Call remote_notice_new_inferior
with RUNNING set to 1 when handling fork events.
---
gdb/remote.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/gdb/remote.c b/gdb/remote.c
index f09a06e..ab750a7 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -6818,7 +6818,14 @@ process_stop_reply (struct stop_reply *stop_reply,
VEC_free (cached_reg_t, stop_reply->regcache);
}
- remote_notice_new_inferior (ptid, 0);
+ /* If a fork event arrived before we knew about the parent thread,
+ make sure to mark it as running when it is created. */
+ if (status->kind == TARGET_WAITKIND_FORKED
+ || status->kind == TARGET_WAITKIND_VFORKED)
+ remote_notice_new_inferior (ptid, 1);
+ else
+ remote_notice_new_inferior (ptid, 0);
+
remote_thr = demand_private_info (ptid);
remote_thr->core = stop_reply->core;
remote_thr->stop_reason = stop_reply->stop_reason;
--
1.8.1.1
More information about the Gdb-patches
mailing list