aboutsummaryrefslogtreecommitdiff
path: root/gdb/gdbserver
diff options
context:
space:
mode:
authorPedro Alves <palves@redhat.com>2014-11-12 11:17:39 +0000
committerPedro Alves <palves@redhat.com>2014-11-12 11:30:49 +0000
commitc2c118cfe13264f5638f9e3924c7fd05a293ad40 (patch)
tree8ac7652340f2430f8e8d35f9da9bbd953de8520c /gdb/gdbserver
parent78708b7c8ccc2138880217de9bd60eceff683f10 (diff)
downloadgdb-c2c118cfe13264f5638f9e3924c7fd05a293ad40.zip
gdb-c2c118cfe13264f5638f9e3924c7fd05a293ad40.tar.gz
gdb-c2c118cfe13264f5638f9e3924c7fd05a293ad40.tar.bz2
GDBserver: don't resume all threads if the Hc thread disapears
There's code in linux_wait_1 that resumes all threads if the Hc thread disappears. It's the wrong thing to do, as GDB has told GDBserver to resume only one thread, because e.g., the user has scheduler-locking enabled, or because GDB was stepping the program over a breakpoint. Resuming all threads behind GDB's back can't be good in either case. The right thing to do is to detect that that the (only) resumed thread is gone, and let GDB know about it. The Linux backend is already doing that nowadays, since: commit fa96cb382c12b099675c5cc238aaa7352a3fd3d7 Author: Pedro Alves <palves@redhat.com> AuthorDate: Thu Feb 27 14:30:08 2014 +0000 Teach GDBserver's Linux backend about no unwaited-for children (TARGET_WAITKIND_NO_RESUMED). The backend detects that all resumed threads have disappeared, and returns TARGET_WAITKIND_NO_RESUMED to the core of GDBserver, which then reports an error to GDB. There's no need to frob the passed in ptid to wait for the continue thread either -- linux_wait_for_event only returns events for resumed threads. The badness (of resuming threads) can actually be observed in the testsuite, if we force-disable vCont support in GDBserver -- before the patch, gdb.threads/no-unwaited-for-left.exp hangs if we disable vCont: (gdb) continue Continuing. FAIL: gdb.threads/no-unwaited-for-left.exp: continue to breakpoint: break-here (timeout) ... more cascading timeouts .... After the patch, gdb.threads/no-unwaited-for-left.exp behaves the same with or without vCont support: (gdb) continue Continuing. [New Thread 32226] [Switching to Thread 32226] Breakpoint 2, thread_a (arg=0x0) at /home/pedro/gdb/mygit/build/../src/gdb/testsuite/gdb.threads/no-unwaited-for-left.c:28 28 return 0; /* break-here */ (gdb) PASS: gdb.threads/no-unwaited-for-left.exp: continue to breakpoint: break-here ... continue Continuing. warning: Remote failure reply: E.No unwaited-for children left. [Thread 32222] #1 stopped. (gdb) FAIL: gdb.threads/no-unwaited-for-left.exp: continue stops when the main thread exits Overall, this is also good for getting rid of a RSP detail from the backend. gdb/gdbserver/ 2014-11-12 Pedro Alves <palves@redhat.com> * linux-low.c (linux_wait_1): Don't force a wait for the Hc thread, and don't resume all threads if the Hc thread has exited.
Diffstat (limited to 'gdb/gdbserver')
-rw-r--r--gdb/gdbserver/ChangeLog5
-rw-r--r--gdb/gdbserver/linux-low.c28
2 files changed, 5 insertions, 28 deletions
diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index dbb8ce5..d162844 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -1,5 +1,10 @@
2014-11-12 Pedro Alves <palves@redhat.com>
+ * linux-low.c (linux_wait_1): Don't force a wait for the Hc
+ thread, and don't resume all threads if the Hc thread has exited.
+
+2014-11-12 Pedro Alves <palves@redhat.com>
+
* linux-low.c (linux_request_interrupt): Always send a SIGINT to
the process group instead of to a specific LWP.
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index d870f71..01f11b7 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -2518,34 +2518,6 @@ retry:
in_step_range = 0;
ourstatus->kind = TARGET_WAITKIND_IGNORE;
- /* If we were only supposed to resume one thread, only wait for
- that thread - if it's still alive. If it died, however - which
- can happen if we're coming from the thread death case below -
- then we need to make sure we restart the other threads. We could
- pick a thread at random or restart all; restarting all is less
- arbitrary. */
- if (!non_stop
- && !ptid_equal (cont_thread, null_ptid)
- && !ptid_equal (cont_thread, minus_one_ptid))
- {
- struct thread_info *thread;
-
- thread = (struct thread_info *) find_inferior_id (&all_threads,
- cont_thread);
-
- /* No stepping, no signal - unless one is pending already, of course. */
- if (thread == NULL)
- {
- struct thread_resume resume_info;
- resume_info.thread = minus_one_ptid;
- resume_info.kind = resume_continue;
- resume_info.sig = 0;
- linux_resume (&resume_info, 1);
- }
- else
- ptid = cont_thread;
- }
-
if (ptid_equal (step_over_bkpt, null_ptid))
pid = linux_wait_for_event (ptid, &w, options);
else