From 00aecdcf6224e44fedf31a07340e9da11500fcfb Mon Sep 17 00:00:00 2001 From: Pedro Alves Date: Sat, 21 Apr 2018 18:19:30 +0100 Subject: [PATCH] FreeBSD: Fix 'Couldn't get registers: Device busy' error (PR gdb/23077) As Rajendra SY reported at , several attach-related tests are failing on FreeBSD. The "attach" command errors with "Couldn't get registers: Device busy". When the "attach" command is executed, it calls target_attach -> inf_ptrace_attach, which just does the ptrace(PT_ATTACH), it does not wait for the child to stop with SIGSTOP. Afterwards, the command is complete and we go back to the event loop. The event loop wakes up and we end up in target_wait -> fbsd_wait, and handle the SIGSTOP stop. At the end of execute_command, though, before going back to the event loop, we check if the frame language changed via check_frame_language_change(). That reads the current PC, which is what leads to the registers read that fails. The problem is that we fail to mark the attached-to thread as executing between the initial attach, and the subsequent target_wait. Until we see the thread stop with SIGSTOP, we shouldn't try to read registers off of it. I guess there may a timing issue here - if you're "lucky", the thread may stop before gdb reads its registers, masking the problem. With that fixed, check_frame_language_change() becomes a nop until the thread is marked not-executing again, after target_wait is called and we go through handle_inferior_event -> normal_stop. We haven't seen the problem on Linux because there, the target_attach implementation waits for the thread to stop before returning. Still, that's supposedly hidden from the core, since the Linux target, like most targets, is a '!to_attach_no_wait' target. This fixes: FAIL: gdb.base/attach.exp: attach1, after setting file FAIL: gdb.base/attach.exp: attach2, with no file FAIL: gdb.base/attach.exp: load file manually, after attach2 (re-read) (got interactive prompt) FAIL: gdb.base/attach.exp: attach when process' a.out not in cwd FAIL: gdb.base/dprintf-detach.exp: bai=on ds=gdb dd=on: re-attach to inferior FAIL: gdb.base/dprintf-detach.exp: bai=on ds=gdb dd=off: re-attach to inferior FAIL: gdb.base/dprintf-detach.exp: bai=on ds=call dd=on: re-attach to inferior FAIL: gdb.base/dprintf-detach.exp: bai=on ds=call dd=off: re-attach to inferior FAIL: gdb.base/dprintf-detach.exp: bai=on ds=agent dd=on: re-attach to inferior FAIL: gdb.base/dprintf-detach.exp: bai=on ds=agent dd=off: re-attach to inferior FAIL: gdb.base/dprintf-detach.exp: bai=off ds=gdb dd=on: re-attach to inferior FAIL: gdb.base/dprintf-detach.exp: bai=off ds=gdb dd=off: re-attach to inferior FAIL: gdb.base/dprintf-detach.exp: bai=off ds=call dd=on: re-attach to inferior FAIL: gdb.base/dprintf-detach.exp: bai=off ds=call dd=off: re-attach to inferior FAIL: gdb.base/dprintf-detach.exp: bai=off ds=agent dd=on: re-attach to inferior FAIL: gdb.base/dprintf-detach.exp: bai=off ds=agent dd=off: re-attach to inferior gdb/ChangeLog: 2018-04-21 Pedro Alves Rajendra SY * inf-ptrace.c (inf_ptrace_attach): Mark the thread as executing. * remote.c (extended_remote_attach): In all-stop mode, mark the thread as executing. --- gdb/ChangeLog | 7 +++++++ gdb/inf-ptrace.c | 5 ++++- gdb/remote.c | 5 ++++- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 0db5c46f6cd..70c461a4b3a 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,10 @@ +2018-04-21 Pedro Alves + Rajendra SY + + * inf-ptrace.c (inf_ptrace_attach): Mark the thread as executing. + * remote.c (extended_remote_attach): In all-stop mode, mark the + thread as executing. + 2018-04-19 Philippe Waroquiers * thread.c (thread_apply_all_command): Fix comment. diff --git a/gdb/inf-ptrace.c b/gdb/inf-ptrace.c index e20388658fe..942494bbdac 100644 --- a/gdb/inf-ptrace.c +++ b/gdb/inf-ptrace.c @@ -235,7 +235,10 @@ inf_ptrace_attach (struct target_ops *ops, const char *args, int from_tty) /* Always add a main thread. If some target extends the ptrace target, it should decorate the ptid later with more info. */ - add_thread_silent (inferior_ptid); + thread_info *thr = add_thread_silent (inferior_ptid); + /* Don't consider the thread stopped until we've processed its + initial SIGSTOP stop. */ + set_executing (thr->ptid, true); unpusher.release (); } diff --git a/gdb/remote.c b/gdb/remote.c index f54a38833b3..49013848d55 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -5316,7 +5316,10 @@ extended_remote_attach (struct target_ops *target, const char *args, inferior_ptid = remote_current_thread (inferior_ptid); /* Add the main thread to the thread list. */ - add_thread_silent (inferior_ptid); + thread_info *thr = add_thread_silent (inferior_ptid); + /* Don't consider the thread stopped until we've processed the + saved stop reply. */ + set_executing (thr->ptid, true); } /* Next, if the target can specify a description, read it. We do -- 2.30.2