From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id 2RVmGF8unGlaAgcAWB0awg (envelope-from ) for ; Mon, 23 Feb 2026 05:39:27 -0500 Authentication-Results: simark.ca; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=intel.com header.i=@intel.com header.a=rsa-sha256 header.s=Intel header.b=FpnAwmWw; dkim-atps=neutral Received: by simark.ca (Postfix, from userid 112) id 4B8C01E0BA; Mon, 23 Feb 2026 05:39:27 -0500 (EST) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=ARC_SIGNED,ARC_VALID,BAYES_00, DKIM_INVALID,DKIM_SIGNED,HTML_MESSAGE,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED,RCVD_IN_VALIDITY_CERTIFIED_BLOCKED, RCVD_IN_VALIDITY_RPBL_BLOCKED,RCVD_IN_VALIDITY_SAFE_BLOCKED autolearn=ham autolearn_force=no version=4.0.1 Received: from vm01.sourceware.org (vm01.sourceware.org [38.145.34.32]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPS id AFB2A1E089 for ; Mon, 23 Feb 2026 05:39:25 -0500 (EST) Received: from vm01.sourceware.org (localhost [127.0.0.1]) by sourceware.org (Postfix) with ESMTP id 1D0834BA23DC for ; Mon, 23 Feb 2026 10:39:25 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 1D0834BA23DC Authentication-Results: sourceware.org; dkim=fail reason="signature verification failed" (2048-bit key, unprotected) header.d=intel.com header.i=@intel.com header.a=rsa-sha256 header.s=Intel header.b=FpnAwmWw Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.21]) by sourceware.org (Postfix) with ESMTPS id C2CDD4BA2E16 for ; Mon, 23 Feb 2026 10:37:08 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org C2CDD4BA2E16 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=intel.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org C2CDD4BA2E16 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=198.175.65.21 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1771843029; cv=none; b=BGxEAHP3V7SdfcGBLN/ee6UjkHpfC6WI8QcQ4FvWVrC6MF83KpYtZfjwbXSNnOy/spTarzJx8efQrNoaGt85FCS2FBoVPk2cbFraBe0c97p4ctWSk2hu9Z48rnTQsFU8ay6hSVpP1qDpx0tAbkOm9+EJBHet1SodNJIuaXknVg4= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1771843029; c=relaxed/simple; bh=6iXQFHdFqx0nPBpGvAXyFhobJ6yhMMV2ToTwBP6pc8g=; h=DKIM-Signature:MIME-Version:From:To:Subject:Date:Message-Id: MIME-Version; b=rf/n/4A45FIF03bZ5yxqw7ZeHEu10N6zongeMq48PVu64VvwsDed5jSsyULnB+1CUBpkcKyN92tXTbMUNnMVeElMbQ3MQACAH9c2P7NPnRkIl0iRsKMHoIIvH9YeOn6Rqv6Mnf/IPotjuZdvNmrDiLH95DIismjm79oNp/2imNw= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1771843029; x=1803379029; h=from:to:subject:date:message-id:in-reply-to:references; bh=6iXQFHdFqx0nPBpGvAXyFhobJ6yhMMV2ToTwBP6pc8g=; b=FpnAwmWwj4TBIohKrSHwqFfeplwjibd/7hDpR90Fg0teNN0g4EOFuNIr lsLGnMFoLXvJKUF7N6A09ug0VfB0FSHyunLuHcxvjC7P/oz0LObQeFrqU 1voPnj7h0+vS77l3tsfdrQomfTKunBVKZtnD0FgQ/8JfKWyN2vP7GAIJM FSmHXO2J3DoYTGDdGolE3Hmc8NQM6alccDKTsaeLJVaPGyz4VKinyBFfl YpP8C5v4fFuF/41pPHabAeg2wqkYI9Vxxtf84txYTrisImEnfoSe+pUTF F0bmBL2gqPmZia4x+73QjC8BJtYH9vh6BWHfFb9m8eky4pyu7LYy7zlSf Q==; X-CSE-ConnectionGUID: 1babeYngR0K7QztuWTWuOw== X-CSE-MsgGUID: rffArwKDQxmAOMLFSkutqQ== X-IronPort-AV: E=McAfee;i="6800,10657,11709"; a="72712711" X-IronPort-AV: E=Sophos;i="6.21,306,1763452800"; d="scan'208";a="72712711" Content-Type: multipart/mixed; boundary="===============4674129003485316545==" MIME-Version: 1.0 Received: from fmviesa006.fm.intel.com ([10.60.135.146]) by orvoesa113.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 23 Feb 2026 02:37:07 -0800 X-CSE-ConnectionGUID: xckcSEiPSIybkwF4vrsyZQ== X-CSE-MsgGUID: doMTic02QXKW7FOmdtGGBQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.21,306,1763452800"; d="scan'208";a="213481195" Received: from gkldtt-dev-004.igk.intel.com (HELO localhost) ([10.123.221.202]) by fmviesa006-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 23 Feb 2026 02:37:06 -0800 From: Tankut Baris Aktemur To: gdb-patches@sourceware.org Subject: [PATCH v3] gdb/infrun: do not restart a stepped thread if not running Date: Mon, 23 Feb 2026 11:36:55 +0100 Message-Id: <20260223103655.4050848-1-tankut.baris.aktemur@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230620152455.471716-1-tankut.baris.aktemur@intel.com> References: <20230620152455.471716-1-tankut.baris.aktemur@intel.com> MIME-Version: 1.0 X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces~public-inbox=simark.ca@sourceware.org --===============4674129003485316545== Content-Transfer-Encoding: 8bit ====== Changes in V3: * Addressed Kevin's comments from https://sourceware.org/pipermail/gdb-patches/2026-February/225235.html * Rebased on the current master; ran regression tests again. Changes in V2: * Changed the thread state check to `(tp->state != THREAD_RUNNING)`. * Rebased on the current master. The latest discussion was https://sourceware.org/pipermail/gdb-patches/2023-May/199613.html ====== Suppose we have two inferiors on an all-stop target with schedule-multi set on: $ gdb -q (gdb) target extended-remote | gdbserver --multi - Remote debugging using | gdbserver --multi - Remote debugging using stdio (gdb) file /temp/test Reading symbols from /temp/test... (gdb) set remote exec-file /temp/test (gdb) start Temporary breakpoint 1 at 0x115c: file test.c, line 8. Starting program: /temp/test stdin/stdout redirected Process /temp/test created; pid = 864027 ... Temporary breakpoint 1, main (argc=1, argv=0x7fffffffd218) at test.c:8 8 foo(); (gdb) add-inferior [New inferior 2] Added inferior 2 on connection 1 (extended-remote | gdbserver --multi -) (gdb) inferior 2 [Switching to inferior 2 [] ()] (gdb) file /temp/test Reading symbols from /temp/test... (gdb) set remote exec-file /temp/test (gdb) tbreak 2 Temporary breakpoint 2 at 0x555555555131: /temp/test.c:2. (2 locations) (gdb) run Starting program: /temp/test stdin/stdout redirected Process /temp/test created; pid = 864430 ... Thread 2.1 "test" hit Temporary breakpoint 2, foo () at test.c:2 2 int a = 42; (gdb) set schedule-multi on (gdb) At this point, detaching the first inferior works fine: (gdb) detach inferiors 1 Detaching from program: /temp/test, process 858904 Detaching from process 858904 [Inferior 1 (process 858904) detached] (gdb) info inferiors Num Description Connection Executable 1 1 (extended-remote | gdbserver --multi -) /temp/test * 2 process 858925 1 (extended-remote | gdbserver --multi -) /temp/test (gdb) Let us now repeat exactly the same scenario, but before detaching, we make the current thread single-step an instruction: ... Thread 2.1 "test" hit Temporary breakpoint 2, foo () at test.c:2 2 int a = 42; (gdb) stepi 3 int b = 43; (gdb) detach inferiors 1 Detaching from program: /temp/test, process 876580 Detaching from process 876580 gdbserver: Couldn't reap LWP 876580 while detaching: No child processes [Inferior 1 (process 876580) detached] (gdb) [Switching to Thread 877351.877351] 3 int b = 43; There is a mysterious line info output. Running the scenario with infrun debug logs reveals more information. ... Thread 2.1 "test" hit Temporary breakpoint 2, foo () at test.c:2 2 int a = 42; (gdb) stepi 3 int b = 43; (gdb) set debug infrun on (gdb) detach inferiors 1 [infrun] scoped_disable_commit_resumed: reason=detaching [infrun] scoped_disable_commit_resumed: reason=detaching Detaching from program: /temp/test, process 3537498 Detaching from process 3537498 gdbserver: Couldn't reap LWP 3537498 while detaching: No child processes [Inferior 1 (process 3537498) detached] [infrun] reset: reason=detaching [infrun] start_step_over: enter [infrun] start_step_over: stealing global queue of threads to step, length = 0 [infrun] operator(): step-over queue now empty [infrun] start_step_over: exit [infrun] restart_stepped_thread: switching back to stepped thread (stepping) [infrun] keep_going_stepped_thread: resuming previously stepped thread [infrun] keep_going_stepped_thread: expected thread advanced also (0x555555555131 -> 0x555555555138) [infrun] clear_step_over_info: clearing step over info [infrun] do_target_resume: resume_ptid=-1.0.0, step=0, sig=GDB_SIGNAL_0 [infrun] infrun_async: enable=1 [infrun] reset: reason=detaching [infrun] maybe_set_commit_resumed_all_targets: enabling commit-resumed for target extended-remote [infrun] maybe_call_commit_resumed_all_targets: calling commit_resumed for target extended-remote (gdb) [infrun] fetch_inferior_event: enter [infrun] scoped_disable_commit_resumed: reason=handling event [infrun] do_target_wait: Found 2 inferiors, starting at #0 [infrun] random_pending_event_thread: None found. [infrun] print_target_wait_results: target_wait (-1.0.0 [process -1], status) = [infrun] print_target_wait_results: 3537875.3537875.0 [Thread 3537875.3537875], [infrun] print_target_wait_results: status->kind = STOPPED, sig = GDB_SIGNAL_TRAP [infrun] handle_inferior_event: status->kind = STOPPED, sig = GDB_SIGNAL_TRAP [infrun] context_switch: Switching context from 0.0.0 to 3537875.3537875.0 [infrun] handle_signal_stop: stop_pc=0x555555555138 [infrun] handle_signal_stop: [3537875.3537875.0] hit its single-step breakpoint [infrun] handle_signal_stop: delayed software breakpoint trap, ignoring [infrun] process_event_stop_test: stepi/nexti [infrun] stop_waiting: stop_waiting [Switching to Thread 3537875.3537875] 3 } [infrun] infrun_async: enable=0 [infrun] reset: reason=handling event [infrun] maybe_set_commit_resumed_all_targets: not requesting commit-resumed for target extended-remote, no resumed threads [infrun] fetch_inferior_event: exit GDB attempted to do a step-over for the current thread. This takes us to the commit that introduced restarting step-overs: commit 408f66864a1a823591b26420410c982174c239a2 Author: Pedro Alves Date: Mon Jan 11 20:01:58 2021 +0000 detach in all-stop with threads running A following patch will add a testcase that has a number of threads constantly stepping over a breakpoint, and then has GDB detach the process, while threads are running. If we have more than one inferior running, and we detach from just one of the inferiors, we expect that the remaining inferior continues running. However, in all-stop, if GDB needs to pause the target for the detach, nothing is re-resuming the other inferiors after the detach. "info threads" shows the threads as running, but they really aren't. This fixes it. However, the thread that was resumed for step-over in our scenario did not have an interrupted step-over; it had completed its stepi already. More debugging reveals that the thread is resumed because of the following two conditions in `restart_stepped_thread`: if (tp->control.trap_expected) { infrun_debug_printf ("switching back to stepped thread (step-over)"); if (keep_going_stepped_thread (tp)) return true; } and if (tp->control.step_range_end) { infrun_debug_printf ("switching back to stepped thread (stepping)"); if (keep_going_stepped_thread (tp)) return true; } The root cause of the problem is, `restart_stepped_thread` checks for the thread state as if (tp->state == THREAD_EXITED) continue; but the thread's state is THREAD_STOPPED. To fix, we change the state check to if (tp->state != THREAD_RUNNING) Additionally, the 'trap_expected' and the 'step_range_end' fields of the thread's control remain set even after the "stepi" command completes, creating a half-baked internal state that can be misleading when debugging. We address this problem by clearing the control fields when stepping completes. We also add a regression test. Regression-tested on X86_64 Linux using the default, native-gdbserver, and native-extended-gdbserver board files. Tested-By: Guinevere Larsen --- gdb/infrun.c | 7 ++- gdb/testsuite/gdb.multi/detach-stepi.c | 30 +++++++++++ gdb/testsuite/gdb.multi/detach-stepi.exp | 69 ++++++++++++++++++++++++ 3 files changed, 104 insertions(+), 2 deletions(-) create mode 100644 gdb/testsuite/gdb.multi/detach-stepi.c create mode 100644 gdb/testsuite/gdb.multi/detach-stepi.exp diff --git a/gdb/infrun.c b/gdb/infrun.c index 6bcd8ec5cc0..ee5551cb483 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -8459,7 +8459,7 @@ restart_stepped_thread (process_stratum_target *resume_target, for (thread_info &tp : all_threads_safe ()) { - if (tp.state == THREAD_EXITED) + if (tp.state != THREAD_RUNNING) continue; if (tp.has_pending_waitstatus ()) @@ -8483,7 +8483,7 @@ restart_stepped_thread (process_stratum_target *resume_target, for (thread_info &tp : all_threads_safe ()) { - if (tp.state == THREAD_EXITED) + if (tp.state != THREAD_RUNNING) continue; if (tp.has_pending_waitstatus ()) @@ -9204,6 +9204,9 @@ static void end_stepping_range (struct execution_control_state *ecs) { ecs->event_thread->control.stop_step = 1; + ecs->event_thread->control.trap_expected = 0; + ecs->event_thread->control.step_range_start = 0; + ecs->event_thread->control.step_range_end = 0; stop_waiting (ecs); } diff --git a/gdb/testsuite/gdb.multi/detach-stepi.c b/gdb/testsuite/gdb.multi/detach-stepi.c new file mode 100644 index 00000000000..45d8d0c14b4 --- /dev/null +++ b/gdb/testsuite/gdb.multi/detach-stepi.c @@ -0,0 +1,30 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2022-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 . */ + +void +a_function (void) +{ + int a = 42; +} + +int +main (void) +{ + int b = 43; + a_function (); + return 0; +} diff --git a/gdb/testsuite/gdb.multi/detach-stepi.exp b/gdb/testsuite/gdb.multi/detach-stepi.exp new file mode 100644 index 00000000000..74beb022bfd --- /dev/null +++ b/gdb/testsuite/gdb.multi/detach-stepi.exp @@ -0,0 +1,69 @@ +# This testcase is part of GDB, the GNU debugger. + +# Copyright 2022-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 . + +# Test detaching from an inferior after a thread in another inferior +# completes a stepi. This is a regression test for a bug that was +# causing an inadvertent resume of the just-stepped thread. + +standard_testfile + +require allow_multi_inferior_tests + +if {[prepare_for_testing "failed to prepare" $testfile $srcfile]} { + return -1 +} + +if {![runto_main]} { + return -1 +} + +delete_breakpoints + +# Set up inferior 2. +gdb_test "add-inferior" "Added inferior .*" \ + "add another inferior" +gdb_test "inferior 2" "Switching to inferior .*" \ + "switch inferior" + +gdb_load $binfile +if {![runto "a_function"]} { + return -1 +} + +gdb_test "info inferiors" ".*" "info inferiors for logging" + +# The bug for which this regression test is written appears in +# schedule-multi mode. +gdb_test_no_output "set schedule-multiple on" + +# Single-step the thread in Inferior 2, then detach Inferior 1. +gdb_test "info threads" ".*" "threads before stepi" +gdb_test "stepi" ".*" +gdb_test "info threads" ".*" "threads after stepi" + +gdb_test "detach inferior 1" "Inferior 1 \[^\r\n\]+ detached\\]" + +# Bad GDB did an unexpected switch to a thread after the detach +# command above. +gdb_test_multiple "print 123" "no unexpected switch" { + -re "Switching to .*" { + fail $gdb_test_name + } + -re -wrap "" { + pass $gdb_test_name + } +} -- 2.34.1 --===============4674129003485316545== Content-Type: multipart/alternative; boundary="===============0681918503667305176==" MIME-Version: 1.0 Content-Disposition: inline --===============0681918503667305176== Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Intel Deutschland GmbH Registered Address: Dornacher Stra=C3=9Fe 1, 85622 Feldkirchen, Germany Tel: +49 89 991 430, www.intel.de Managing Directors: Harry Demas, Jeffrey Schneiderman, Yin Chong Sorrell Chairperson of the Supervisory Board: Nicole Lau Registered Seat: Munich Commercial Register: Amtsgericht M=C3=BCnchen HRB 186928 --===============0681918503667305176== Content-Type: text/html; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable

Intel Deutschland GmbH

Registered Ad= dress: Dornacher Stra=C3=9Fe 1, 85622 Feldkirchen, Germany
Tel: +49 89 = 991 430, www.intel.de
Managing Directors: Harry Demas, Jeffrey Schneide= rman, Yin Chong Sorrell
Chairperson of the Supervisory Board: Nicole La= u
Registered Seat: Munich
Commercial Register: Amtsgericht M=C3=BCn= chen HRB 186928

--===============0681918503667305176==-- --===============4674129003485316545==--