From: Markus Metzger <markus.t.metzger@intel.com>
To: gdb-patches@sourceware.org
Subject: [PATCH] gdb, infrun: do not discard a step-completed pending waitstatus
Date: Tue, 15 Sep 2026 16:14:41 +0200 [thread overview]
Message-ID: <20260915141441.2274270-1-markus.t.metzger@intel.com> (raw)
Consider a scenario with two breakpoints on adjacent instructions:
bp1 at 0xf00
bp2 at 0xf01
as well as two threads in all-stop-on-top-of-non-stop mode.
Assume that threads A hits bp1 and we report the breakpoint hit to the
user. When the user continues, we start a step-over for thread A at 0xf00.
Assume that thread B now hits bp1 and we report the breakpoint hit to the
user. We stop all threads to report the event. Meanwhile, the step-over
of thread A completes, so we save the pending waitstatus (stop_pc=0xf01,
currently_stepping=1) of thread A.
When the user continues, clear_proceed_status_thread() discards the
pending step completed waitstatus of thread A, and proceed() starts
another step-over for thread A at 0xf01.
We skip bp2 for thread A.
Remove the code in clear_proceed_status_thread() that discards a step
completed waitstatus and let it get handled normally.
---
gdb/infrun.c | 25 ++-----
gdb/testsuite/gdb.threads/adjacent-bp.c | 48 +++++++++++++
gdb/testsuite/gdb.threads/adjacent-bp.exp | 86 +++++++++++++++++++++++
3 files changed, 139 insertions(+), 20 deletions(-)
create mode 100644 gdb/testsuite/gdb.threads/adjacent-bp.c
create mode 100644 gdb/testsuite/gdb.threads/adjacent-bp.exp
diff --git a/gdb/infrun.c b/gdb/infrun.c
index b9618fb6422..4ab9f4aaf64 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -3100,28 +3100,13 @@ clear_proceed_status_thread (struct thread_info *tp)
infrun_debug_printf ("%s", tp->ptid.to_string ().c_str ());
gdb_assert (tp->internal_state () != THREAD_INT_RUNNING);
- /* If we're starting a new sequence, then the previous finished
- single-step is no longer relevant. */
if (tp->has_pending_waitstatus ())
{
- if (tp->stop_reason () == TARGET_STOPPED_BY_SINGLE_STEP)
- {
- infrun_debug_printf ("pending event of %s was a finished step. "
- "Discarding.",
- tp->ptid.to_string ().c_str ());
-
- tp->set_internal_state (THREAD_INT_STOPPED);
- tp->clear_pending_waitstatus ();
- tp->set_stop_reason (TARGET_STOPPED_BY_NO_REASON);
- }
- else
- {
- infrun_debug_printf
- ("thread %s has pending wait status %s (currently_stepping=%d).",
- tp->ptid.to_string ().c_str (),
- tp->pending_waitstatus ().to_string ().c_str (),
- tp->control.currently_stepping);
- }
+ infrun_debug_printf
+ ("thread %s has pending wait status %s (currently_stepping=%d).",
+ tp->ptid.to_string ().c_str (),
+ tp->pending_waitstatus ().to_string ().c_str (),
+ tp->control.currently_stepping);
}
/* If this signal should not be seen by program, give it zero.
diff --git a/gdb/testsuite/gdb.threads/adjacent-bp.c b/gdb/testsuite/gdb.threads/adjacent-bp.c
new file mode 100644
index 00000000000..e72e674f52a
--- /dev/null
+++ b/gdb/testsuite/gdb.threads/adjacent-bp.c
@@ -0,0 +1,48 @@
+/* Copyright 2026 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <unistd.h>
+
+static pthread_barrier_t barrier;
+
+static void *
+test (void *arg)
+{
+ pthread_barrier_wait (&barrier);
+ int a = 0; /* break here. */
+ int b = 0;
+ int c = 0;
+ return arg;
+}
+
+int
+main ()
+{
+ pthread_t th;
+
+ alarm (500);
+
+ pthread_barrier_init (&barrier, NULL, 2);
+ pthread_create (&th, NULL, test, NULL);
+ test (NULL);
+
+ pthread_join (th, NULL);
+ pthread_barrier_destroy (&barrier);
+
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.threads/adjacent-bp.exp b/gdb/testsuite/gdb.threads/adjacent-bp.exp
new file mode 100644
index 00000000000..9e7782c01c2
--- /dev/null
+++ b/gdb/testsuite/gdb.threads/adjacent-bp.exp
@@ -0,0 +1,86 @@
+# Copyright 2026 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Test that GDB does not skip a breakpoint when a step-over completes
+# while another event leads to a stop.
+
+standard_testfile
+
+if {[prepare_for_testing "failed to prepare" ${testfile} ${srcfile} \
+ {debug pthreads}]} {
+ return
+}
+
+if {![runto_main]} {
+ return
+}
+
+# Find a sequence of adjacent instructions.
+set bp_line [gdb_get_line_number "break here"]
+set pcs {}
+gdb_test_multiple "info line $bp_line" "" {
+ -re -wrap "starts at address ($hex).*" {
+ pass $gdb_test_name
+
+ set line "\\s+($hex) \[^\r\n\]+"
+ gdb_test_multiple "x/3i $expect_out(1,string)" "disassemble" {
+ -re -wrap "$line\r\n$line\r\n$line.*" {
+ pass $gdb_test_name
+
+ lappend pcs $expect_out(1,string)
+ lappend pcs $expect_out(2,string)
+ lappend pcs $expect_out(3,string)
+ }
+ -re -wrap "" {
+ fail $gdb_test_name
+ }
+ }
+ }
+ -re -wrap "" {
+ fail $gdb_test_name
+ }
+}
+
+# Set breakpoints on adjacent instructions.
+foreach pc $pcs {
+ gdb_breakpoint "\*$pc"
+}
+
+# Continue from breakpoint to breakpoint.
+set hits [dict create]
+set iter 0
+gdb_test_multiple "continue" "" {
+ -re -wrap "hit Breakpoint.*" {
+ dict incr hits [get_hexadecimal_valueof "\$pc" invalid "stop $iter"]
+ incr iter
+ send_gdb "continue\n"
+ exp_continue
+ }
+ -re -wrap "$inferior_exited_re normally.*" {
+ pass "$gdb_test_name"
+ }
+}
+
+# We expect all breakpoints to be hit by both threads.
+foreach pc $pcs {
+ if {[dict exists $hits $pc]} {
+ gdb_assert {[dict get $hits $pc] eq 2} "breakpoint at $pc"
+ dict unset hits $pc
+ } else {
+ fail "breakpoint at $pc"
+ }
+}
+# And no unrelated stops.
+gdb_assert {[dict size $hits] eq 0} "no extra stops"
--
2.53.0
________________________________________
Intel Deutschland GmbH
Registered Address: Dornacher Strasse 1, 85622 Feldkirchen, Germany
Tel: +49 (89) 99143-0
www.intel.de
Managing Directors: Candice Moore, Jeffrey Schneiderman, Ramachandran Sitaraman
Chairperson of the Supervisory Board: Sonja Pierer
Registered Seat: Munich Commercial Register B: Amtsgericht Munich HRB 186928
This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.
reply other threads:[~2026-09-15 14:15 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260915141441.2274270-1-markus.t.metzger@intel.com \
--to=markus.t.metzger@intel.com \
--cc=gdb-patches@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox