FreeBSD: Fix 'Couldn't get registers: Device busy' error (PR gdb/23077)
authorPedro Alves <palves@redhat.com>
Sat, 21 Apr 2018 17:19:30 +0000 (18:19 +0100)
committerPedro Alves <palves@redhat.com>
Sat, 21 Apr 2018 17:19:30 +0000 (18:19 +0100)
As Rajendra SY reported at
<https://sourceware.org/ml/gdb-patches/2018-04/msg00399.html>, 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  <palves@redhat.com>
    Rajendra SY  <rajendra.sy@gmail.com>

* 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
gdb/inf-ptrace.c
gdb/remote.c

index 0db5c46f6cda299216d539faa7b5cca7f2b10d47..70c461a4b3ac04e1b0de4fee0e8b687cbc3d1e9e 100644 (file)
@@ -1,3 +1,10 @@
+2018-04-21  Pedro Alves  <palves@redhat.com>
+           Rajendra SY  <rajendra.sy@gmail.com>
+
+       * 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  <philippe.waroquiers@skynet.be>
 
        * thread.c (thread_apply_all_command): Fix comment.
index e20388658fecae56474e816ebf335da6ddb455fe..942494bbdacdb57a172455cc5b89f11fe4d527fa 100644 (file)
@@ -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 ();
 }
index f54a38833b30d090d46b186a0481c4276011dddf..49013848d5553dd1da0b014d3ef8001bfb65ca89 100644 (file)
@@ -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