]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commit
Sync thread state after infcalls with "set unwind-on-* on" (PR gdb/34148) master
authorPedro Alves <pedro@palves.net>
Mon, 18 May 2026 13:20:00 +0000 (14:20 +0100)
committerPedro Alves <pedro@palves.net>
Tue, 26 May 2026 12:42:11 +0000 (13:42 +0100)
commit4e51e5abc5c45332dfddd5a0434f3a4792e9c370
treef185ad3f4e298d90d1babc011e619b87108096de
parenta8740b7533b4df34d4d7bc5be9bb2108d019fce5
Sync thread state after infcalls with "set unwind-on-* on" (PR gdb/34148)

Commit 519774805a1 ("Don't pretend infcalls don't set the inferior
running (PR gdb/34082)") removed the special case in proceed that
skipped set_state(THREAD_RUNNING) for infcalls.  That fixed
gdb.threads/hand-call-new-thread.exp, but introduced a regression in
gdb.compile/compile.exp:

 ...
 set unwind-on-signal on
 (gdb) PASS: gdb.compile/compile.exp: set unwind-on-signal on
 compile code *(volatile int *) 0 = 0;
 The program being debugged received signal SIGSEGV, Segmentation fault
 while in a function called from GDB.  GDB has restored the context
 to what it was before the call.  To change this behavior use
 "set unwind-on-signal off".  Evaluation of the expression containing
 the function (_gdb_expr) will be abandoned.
 (gdb) PASS: gdb.compile/compile.exp: compile code segfault second
 break 132
 Breakpoint 2 at 0x555555555262: file .../compile.c, line 132.
 (gdb) continue
 Cannot execute this command while the selected thread is running.
 (gdb) FAIL: gdb.compile/compile.exp: continue to breakpoint: break-here

The "compile code" command before the FAIL is an infcall under the
hood.  That hits SIGSEGV with "set unwind-on-signal on" in effect, so
GDB unwinds and abandons the call.  After that, "continue" is rejected
because the thread is still marked THREAD_RUNNING from the proceed
that started the infcall.

When an infcall is unwound due to a signal, timeout, or terminating
exception, call_thread_fsm::should_notify_stop returns false, and so
normal_stop is not called from fetch_inferior_event.  normal_stop is
what would normally call finish_thread_state to sync the public thread
state back to THREAD_STOPPED.  run_inferior_call has a fallback
finish_thread_state call for that purpose, but it is gated on
stop_stack_dummy == STOP_STACK_DUMMY, which is only true for
successful calls.

Before the commit mentioned above, proceed never marked an infcall's
thread as THREAD_RUNNING, so the missing RUNNING => STOPPED transition
was harmless.  The old comment in infcall.c about the
finish_thread_state call claimed "If the infcall does NOT succeed,
normal_stop will have already finished the thread states", but that
was already incorrect for the unwind paths.  It just happened to not
matter.

Fix this by dropping the STOP_STACK_DUMMY guard and updating the
comment to describe the actual rule: sync regardless of how the call
ended.  The !was_running check is kept since it is there to exclude
the in-cond-eval case, where the thread is meant to stay marked
running.  finish_thread_state is idempotent, so the call is harmless
on paths where normal_stop also ran.

Extend gdb.base/unwindonsignal.exp to exercise the "set
unwind-on-signal on" path without having to rely on the "compile code"
feature.  Without the fix, the test fails like so:

 info threads
   Id   Target Id                                           Frame
 * 1    Thread 0x7ffff7f8f740 (LWP 239019) "unwindonsignal" (running)
 (gdb) FAIL: gdb.base/unwindonsignal.exp: thread is stopped
 continue
 Cannot execute this command while the selected thread is running.
 (gdb) FAIL: gdb.base/unwindonsignal.exp: continue until exit at after unwound infcall

Similarly, extend gdb.cp/gdb2495.exp for "set
unwind-on-terminating-exception on", and gdb.base/infcall-timeout.exp
for "set unwind-on-timeout on".  Both would fail without the code fix,
too.

With the fix, gdb.compile/compile.exp now passes cleanly.

Tested on x86_64-unknown-linux-gnu.

Approved-By: Andrew Burgess <aburgess@redhat.com>
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=34148
Change-Id: Idef0dcd4dd751b501869c58b752f77d4dadb6c72
gdb/infcall.c
gdb/testsuite/gdb.base/infcall-timeout.exp
gdb/testsuite/gdb.base/unwindonsignal.exp
gdb/testsuite/gdb.cp/gdb2495.exp