Linux: don't resume new LWPs until we've pulled all events out of the kernel
authorPedro Alves <palves@redhat.com>
Wed, 4 Feb 2015 18:13:28 +0000 (19:13 +0100)
committerPedro Alves <palves@redhat.com>
Wed, 4 Feb 2015 18:13:28 +0000 (19:13 +0100)
commit20ba1ce66d31b9dd16ed8c648f46ce32aa3a03e0
tree2f33431e75790cfddfac5f6ef30f175f826f9af1
parent3c537f7fdb11f02f7082749f3f21dfdd2c2025e8
Linux: don't resume new LWPs until we've pulled all events out of the kernel

Since the starvation avoidance series
(https://sourceware.org/ml/gdb-patches/2014-12/msg00631.html), both
GDB and GDBserver pull all events out of ptrace before deciding which
event to process.

There's one problem with that though.  Because we resume new threads
immediately when we see a PTRACE_EVENT_CLONE event, if the program
constantly spawns threads fast enough, new threads can spawn threads
faster we can pull events out of the kernel, and thus we'd get stuck
in an infinite loop, never returning any event to the core to process.
I occasionally see this happen with the
attach-many-short-lived-threads.exp test against gdbserver.

The fix is to delay resuming new threads until we've pulled out all
events out of the kernel.

On native, we already have the resume_stopped_resumed_lwps function
that knows to resume LWPs that are stopped with no event to report to
the core.  So the patch just adds another use.  GDBserver didn't have
the equivalent yet, so the patch adds one.

Tested on x86_64 Fedora 20, native and gdbserver (remote and
extended-remote).

gdb/gdbserver/ChangeLog:
2015-02-04  Pedro Alves  <palves@redhat.com>

* linux-low.c (handle_extended_wait): Don't resume LWPs here.
(resume_stopped_resumed_lwps): New function.
(linux_wait_for_event_filtered): Use it.

gdb/ChangeLog:
2015-02-04  Pedro Alves  <palves@redhat.com>

* linux-nat.c (handle_extended_wait): Don't resume LWPs here.
(wait_lwp): Don't call wait_lwp if linux_handle_extended_wait
returns true.
(resume_stopped_resumed_lwps): Don't check whether the thread is
marked as executing.
(linux_nat_wait_1): Use resume_stopped_resumed_lwps.
gdb/ChangeLog
gdb/gdbserver/ChangeLog
gdb/gdbserver/linux-low.c
gdb/linux-nat.c