]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commit
infrun: with AS+NS, prefer process exit over thread exit
authorPedro Alves <pedro@palves.net>
Wed, 14 May 2025 18:02:34 +0000 (19:02 +0100)
committerPedro Alves <pedro@palves.net>
Mon, 19 May 2025 13:12:37 +0000 (14:12 +0100)
commit3d28f9b2dc4fde972bdd570bd3e91002e84668d2
tree180204c1b2c0585438519528dbba5c96f09164a4
parenta31aad3284e02583bcc0800898d792f34a5ab446
infrun: with AS+NS, prefer process exit over thread exit

This patch fixes gdb.base/ending-run.exp for Windows when the target
backend supports notifying infrun about thread exit events (which is
added by the Windows non-stop support, later).

Without this patch, and with the Windows target in non-stop mode
("maint set target-non-stop on"), we get, when stepping out of main:

 (gdb) PASS: gdb.base/ending-run.exp: Step to return
 next
 32      }
 (gdb) next
 [Thread 7956.0x2658 exited]
 [Thread 7956.0x2500 exited]
 [Thread 7956.0x2798 exited]
 Command aborted, thread exited.
 (gdb) FAIL: gdb.base/ending-run.exp: step out of main

With the patch, we get:

 (gdb) next
 [Thread 9424.0x40c exited]
 [Inferior 1 (process 9424) exited normally]
 (gdb) PASS: gdb.base/ending-run.exp: step out of main

In the failing case, what happens is that "next" enables
target_thread_events.  Then, the main thread causes the whole process
to exit.  On Windows, that makes the main thread report a thread exit
event, followed by thread exit events for all other threads, except
the last thread that happens to be the one that exits last.  That last
one reports an exit-process event instead.

Since "next" enabled target_thread_events, the Windows target backend
reports the main thread's exit event to infrun.  And then, since the
thread that was stepping reported a thread-exit, GDB aborts the "next"
command.

Stepping out of main is a very common thing to do, and I think
reporting the thread exit in this case when the whole process is
exiting isn't very useful.  I think we can do better.  So instead, if
we're about to report a thread exit in all-stop mode with the backend
in non-stop mode, and while stopping all threads, we see a
whole-process-exit event, prefer processing that event instead of
reporting the original thread exit.

A similar issue can be triggered on GNU/Linux as well, if we step over
an exit syscall that is called by any thread other than main.  This
scenario is exercised by the new testcase added by this patch.

Without the patch, the testcase shows:

 (gdb) next
 [Thread 0x7ffff7a00640 (LWP 3207243) exited]
 warning: error removing breakpoint 0 at 0x5555555551c3
 warning: error removing breakpoint 0 at 0x5555555551c3
 warning: error removing breakpoint 0 at 0x5555555551c3
 Command aborted, thread exited.
 Cannot remove breakpoints because program is no longer writable.
 Further execution is probably impossible.
 (gdb)

This is fixed for GNU/Linux by the patch, which results in:

 (gdb) next
 [Thread 0x7ffff7a00640 (LWP 3230550) exited]
 warning: error removing breakpoint 0 at 0x5555555551c3
 warning: error removing breakpoint 0 at 0x5555555551c3
 warning: error removing breakpoint 0 at 0x5555555551c3
 [Inferior 1 (process 3230539) exited normally]
 (gdb)

Pure all-stop targets (such as GNU/Linux GDBserver unless you force
non-stop with "maint set target-non-stop on") will unfortunately still
have the "Further execution is probably impossible." behavior, because
GDB can't see the process-exit event until the target is re-resumed.
That's unfortunate, but I don't think that should prevent improving
non-stop targets.  (And eventually I would like remote targets to be
always "maint set target-non-stop on" by default if possible, too.)

Change-Id: I56559f13e04aeafd812d15e4b408c8337bca5294
gdb/infrun.c
gdb/testsuite/gdb.threads/step-over-process-exit.c [new file with mode: 0644]
gdb/testsuite/gdb.threads/step-over-process-exit.exp [new file with mode: 0644]