From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id K/8mHQg04mqJtD4AWB0awg (envelope-from ) for ; Wed, 28 Oct 2026 13:42:32 -0400 Authentication-Results: simark.ca; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=L9wg2zu6; dkim-atps=neutral Received: by simark.ca (Postfix, from userid 112) id 5CB70378002; Wed, 28 Oct 2026 13:42:32 -0400 (EDT) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-6.4 required=5.0 tests=ARC_SIGNED,ARC_VALID,BAYES_00, DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham autolearn_force=no version=4.0.1 Received: from vm01.sourceware.org (vm01.sourceware.org [IPv6:2620:52:6:3111::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 455E31E007 for ; Wed, 28 Oct 2026 13:42:31 -0400 (EDT) Received: from vm01.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 1DE144BA2E1C for ; Wed, 28 Oct 2026 17:42:30 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 1DE144BA2E1C Authentication-Results: sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=L9wg2zu6 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTP id DB76C4BA2E05 for ; Wed, 28 Oct 2026 17:42:03 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org DB76C4BA2E05 Authentication-Results: sourceware.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org DB76C4BA2E05 Authentication-Results: sourceware.org; arc=none smtp.remote-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1793209324; cv=none; b=nJ/xIDx9UE8h29RWrNZCtSIaq7BHhY/UPkww9yIRTCGXGbu9Xrt1FiUalObU70yhMfE2DTqaVucUzlOt5v076Ukje6wby/YvJTh3jv64ZEpjvIqXv7WpSI6IzO3OrjAwSVL6VTdrWx9pG2fzEZITxzpCKiUcZl/s2htz7EFuHek= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1793209324; c=relaxed/simple; bh=Fvd3GHrrixuZEONKIai/T6MCqlA3BbA8xHR6cAc59g4=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=jW6vpREw92POgC0pls+YgGnjAyXkZl3MzQKHKOu7oqrWhriT978KpmXO3ZBHKDQbWEE7lxChGUQW/dV/8zad5wTxmpuDgGwkMkJ3baHvJpcjjn4KnfT9v8DVGipES2bE+r1GU1xFSAM5ugdXdai+Lt5NIAbN0AAXcUUDBwWrcyQ= ARC-Authentication-Results: i=1; sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=L9wg2zu6 DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org DB76C4BA2E05 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1793209322; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=JtlMt+rpvRScVVToIfCrZ9Tzr67i6ypDv7madFTLNeY=; b=L9wg2zu6i0kvjqyRb597v1OaNfIcdUjqbwEhsPwAaJpEgnJZz7tshQMbaHl/Atl5uxJo57 0bbJcXWDTALBdTk16RUuo7de2LJmlxI7OC6/87qDJPoAVfmq8CybA94Hez4fLtREQepqWO jYsbYGsWTHJsJobogq51lbWWGKLP9oE= Received: from mail-wr1-f72.google.com (mail-wr1-f72.google.com [209.85.221.72]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-694-wP6G7xMVMiW43OzbPXmtFg-1; Wed, 28 Oct 2026 13:41:59 -0400 X-MC-Unique: wP6G7xMVMiW43OzbPXmtFg-1 X-Mimecast-MFC-AGG-ID: wP6G7xMVMiW43OzbPXmtFg_1793209319 Received: by mail-wr1-f72.google.com with SMTP id ffacd0b85a97d-48c6a1d4034so1085419f8f.0 for ; Wed, 28 Oct 2026 10:41:59 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1793209318; x=1793814118; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=JtlMt+rpvRScVVToIfCrZ9Tzr67i6ypDv7madFTLNeY=; b=PaPoXr9OYb6oeDHUOIeJ38VOgYndc7i9A2VOlCz3HXXFZdPK0cwzj0XI0AsGvqV4hi qohB03GFPANHWDPg1M3LXKeWW02EpV5VgOU588Tw/r3ANVUap15Wc3+FSh426arV8ncZ 7dV0LFp4Qn4m7eyzRVJJG1HazNwKvV20FPxJpxd49b1aTah8I8cguDl5k5SNv3eFcrW9 jj42uCrEaaEwkh2ncCTjh64SADgbFeMpeHvzGIPgk1Zsb4H05JJljFm2yYeuguXASZZi VQTKeO1g9lO2+GO4QL3aWEToeIIlkmWBkIYAhBMbnNdAnqdrfzE4EcSrpNneo5raAE+8 0M1w== X-Gm-Message-State: AFq9FYJSsJ7OQrH13h1Sih7WbEoGgtZdDv+wDiHEAFeym1FVQtJYCmd8 gV49irwbmdzMRxhMEJZOeOLYfyqOcepFda25lkeXYGkLuVKpNhW59efTuxhK3VkpPM5x/Ve0vDr YF44cnuqJlRl+umMbftrkDVjqlGyAME6/Y4VlHmbQnL46AYrtcWnsOasDS1F3YmOpw4XI0sXdBe /+CD60ccM1WDJtWA/r7cMOvZ7FS/SVfbA16ABqkfFNUcnSf+0= X-Gm-Gg: AYBFou2hC7ZeERCj1rrWa4hr8FVLCYr6E1pJMrzByKoAqpPlB2tjeqBKfSF9qF3VGLJ NN50Zm6iH3RBzB4vTL2EI480Ip5ogrd2RW0Z5uILFfNCx3o/LHNzstx/iLliYJHfQUtW3HPK5t0 dhFgRbsNvPSR40heSZlA0LtyISVdx5ByaR9OIV5CqcGojyg/jZUzRWzhu3IRkr1nuDuY2coUrc0 Cw+IjnRJM4SEBRTRPU6Jv1Ee8ot3YfMf0WBQUjEUogq4t6QqSsnZDVl5RFqixuls45yy7AVQ+Dw 6RUAC87RxUgtvG/163PyGLw3tqExFjQK9EJgYxIeS5t2GvHOrUm/X3mJCccJBzeexxJMo5MnBsV N8pKIKfe+FABJmgWejSUg+dfCRtbiYfY5QQTEvKqyPgcsJnU= X-Received: by 2002:a05:6000:2481:b0:48b:1c:d6e1 with SMTP id ffacd0b85a97d-48e5d30e165mr6984165f8f.43.1793209318422; Wed, 28 Oct 2026 10:41:58 -0700 (PDT) X-Received: by 2002:a05:6000:2481:b0:48b:1c:d6e1 with SMTP id ffacd0b85a97d-48e5d30e165mr6984089f8f.43.1793209317719; Wed, 28 Oct 2026 10:41:57 -0700 (PDT) Received: from localhost ([2a00:23c6:e11d:fb01:6748:4fce:3e30:6e23]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-48e64ccc693sm351418f8f.5.2026.10.28.10.41.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 28 Oct 2026 10:41:57 -0700 (PDT) From: Andrew Burgess To: gdb-patches@sourceware.org Cc: Andrew Burgess Subject: [PATCH] gdbserver: reset the report_thread_events feature for new connections Date: Wed, 28 Oct 2026 17:41:54 +0000 Message-Id: <7845b61991b27ed7e0b91237b00da2fcab3c2d8c.1793209296.git.aburgess@redhat.com> X-Mailer: git-send-email 2.25.4 MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: plLd8jQpfcmKpLvjpy2e2cej9GkDrVLorM1UuaLI7ws_1793209319 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: 8bit content-type: text/plain; charset="US-ASCII"; x-default=true 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 I noticed that the report_thread_events feature flag (in gdbserver) was not being reset to its default state for each new connection. This flag is turned on when gdbserver receives a QThreadEvents:1 packet, and turned back off with a QThreadEvents:0 packet. GDB usually sends these packets before and after waiting for some event. Normally, by the time GDB returns to a user prompt the QThreadEvents:0 packet will have been sent and report_thread_events will have been returned to its default `off` state. However, it is possible that if GDB broke the connection with gdbserver unexpectedly, for example, if GDB crashed, or the connection dropped, then gdbserver might be left with report_thread_events in the `on` state. If this happened, then when a new GDB reconnected, the flag should be restored to its default `off` state. This is what happens to other similar flags, e.g. the noack_mode flag. See the code in gdbserver/server.cc in the captured_main function, at the top of the 'while (1)' loop; this is the code that resets flags for a new connection. The report_thread_events flag is missing from this block. This commit adds the reset of report_thread_events to the top of this while loop, ensuring the flag is reset on each new connection, and also adds a test for this. The test is a little artificial as we are trying to simulate an unexpected disconnection, but in a controlled manner. To do this I manually send a QThreadEvents:1 packet to turn report_thread_events on and then disconnect. I then turn the thread-events-packet off and reconnect. Finally, I 'set remote debug on' and look in the packet output for an indication that gdbserver is sending thread-event packets. Without the fix this test fails, but passes with the patch in this commit. --- .../gdb.server/reconnect-thread-events.c | 61 ++++++++ .../gdb.server/reconnect-thread-events.exp | 145 ++++++++++++++++++ gdbserver/server.cc | 1 + 3 files changed, 207 insertions(+) create mode 100644 gdb/testsuite/gdb.server/reconnect-thread-events.c create mode 100644 gdb/testsuite/gdb.server/reconnect-thread-events.exp diff --git a/gdb/testsuite/gdb.server/reconnect-thread-events.c b/gdb/testsuite/gdb.server/reconnect-thread-events.c new file mode 100644 index 00000000000..c939030451c --- /dev/null +++ b/gdb/testsuite/gdb.server/reconnect-thread-events.c @@ -0,0 +1,61 @@ +/* This testcase is part of GDB, the GNU debugger. + + 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 . */ + +#include +#include +#include +#include "gdb_watchdog.h" + +volatile int ready = 0; + +void +breakpt_before_thread (void) +{ +} + +void +breakpt_after_thread (void) +{ +} + +static void * +worker (void *arg) +{ + while (!ready) + usleep (1000); + return NULL; +} + +int +main (void) +{ + pthread_t thr; + + gdb_watchdog (120); + + breakpt_before_thread (); + + if (pthread_create (&thr, NULL, worker, NULL) != 0) + abort (); + + breakpt_after_thread (); + + ready = 1; + pthread_join (thr, NULL); + + return 0; +} diff --git a/gdb/testsuite/gdb.server/reconnect-thread-events.exp b/gdb/testsuite/gdb.server/reconnect-thread-events.exp new file mode 100644 index 00000000000..4f84bdce11b --- /dev/null +++ b/gdb/testsuite/gdb.server/reconnect-thread-events.exp @@ -0,0 +1,145 @@ +# 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 . + +# Test that gdbserver correctly resets the report_thread_events flag +# when a new connection is established. +# +# In a normal GDB session the report_thread_events will only be +# switched on (via "QThreadEvents:1" packet) while GDB is waiting for +# some command to complete, after which the flag is disabled again +# using a "QThreadEvents:0" packet. +# +# However, if GDB unexpectedly disconnects while this feature is +# turned on, then when a new GDB connects gdbserver should +# automatically reset this flag. At one point this was not happening. +# This test exists to check for this case. +# +# Connect to gdbserver, manually send QThreadEvents:1 to latch the +# flag on, disconnect, then reconnect with the thread-events packet +# disabled. If gdbserver fails to reset the flag, it will send +# unsolicited T05create:; stop-reply packets for thread creation +# events. Detect this using 'set remote debug on'. + +require {!is_remote target} {!is_remote host} + +load_lib gdbserver-support.exp + +standard_testfile + +require allow_gdbserver_tests + +if { [build_executable "build executable" $testfile $srcfile \ + {debug pthreads}] == -1 } { + return +} + +proc reconnection_and_thread_events {} { + global GDBFLAGS gdbserver_reconnect_p use_gdb_stub + + save_vars { GDBFLAGS } { + # If possible set the sysroot to avoid copying files. + if { ![is_remote host] } { + set GDBFLAGS "$GDBFLAGS -ex \"set sysroot\"" + } + clean_restart $::testfile + + # Make sure we're disconnected, in case we're testing with an + # extended-remote board, therefore already connected. + gdb_test "disconnect" ".*" + } + + save_vars { gdbserver_reconnect_p use_gdb_stub } { + # Setting this flag prevents gdbserver being started with the + # --once option; this is required so that we can reconnect. + set gdbserver_reconnect_p 1 + + # This test always starts gdbserver in --multi mode, so clear + # the use_gdb_stub global to allow gdb_start_cmd to work. + set use_gdb_stub 0 + + set res [gdbserver_start "--multi" "$::binfile"] + set gdbserver_protocol "extended-remote" + set gdbserver_gdbport [lindex $res 1] + + with_test_prefix "first connection" { + gdb_target_cmd $gdbserver_protocol $gdbserver_gdbport + + # Start a new inferior. + if { [gdb_start_cmd] < 0 } { + fail "start command" + return + } + + # gdb_start_cmd doesn't consume the prompt. Collect it now. + gdb_test "" "" "wait for prompt after start" + + gdb_breakpoint "breakpt_before_thread" + gdb_continue_to_breakpoint "before thread creation" + + # Directly send QThreadEvents:1 to latch the flag on in + # gdbserver. This is equivalent to what GDB does during resume + # when thread events are needed, but avoids depending on infrun + # internals that may also send QThreadEvents:0 before we can + # disconnect. + # + # The point here is to emulate an abnormal disconnection; the + # flag is turned on, but never turned off. + gdb_test "maintenance packet QThreadEvents:1" \ + "received: .*OK.*" \ + "send QThreadEvents:1" + + gdb_test "disconnect" ".*" + } + + with_test_prefix "second connection" { + # Disable both thread-events and thread-options packets so + # GDB will not send either on the new connection. + gdb_test "set remote thread-events-packet off" ".*" + gdb_test "set remote thread-options-packet off" ".*" + + # Reconnect. At this point there is already an inferior + # running, we can just pick up the debug session. + gdb_target_cmd $gdbserver_protocol $gdbserver_gdbport + + gdb_breakpoint "breakpt_after_thread" + + # Continue past the thread creation with debug remote enabled. + # If gdbserver failed to reset the report_thread_events flag, + # the thread creation will generate a T05create:; stop-reply + # packet. + gdb_test_no_output "set debug remote on" + + # Continue. Process the output line by line to avoid buffering + # excessive output. Look for a 'T' packet mentioning the + # 'create' stop reason, this should only happen when the + # thread-events-packet is on. + set saw_create false + gdb_test_multiple "continue" \ + "continue without thread-create events" -lbl { + -re "\r\n\[^\r\n\]+Packet received: T\[^\r\n\]+create:\[^\r\n\]+(?=\r\n)" { + set saw_create true + exp_continue + } + -re "\r\n$::gdb_prompt $" { + gdb_assert { !$saw_create } $gdb_test_name + } + } + + gdb_test_no_output -nopass "set debug remote off" + } + } +} + +reconnection_and_thread_events diff --git a/gdbserver/server.cc b/gdbserver/server.cc index 74774fcde7c..34a49cec746 100644 --- a/gdbserver/server.cc +++ b/gdbserver/server.cc @@ -4621,6 +4621,7 @@ captured_main (int argc, char *argv[]) cs.report_fork_events = 0; cs.report_vfork_events = 0; cs.report_exec_events = 0; + cs.report_thread_events = 0; /* Be sure we're out of tfind mode. */ cs.current_traceframe = -1; cs.cont_thread = null_ptid; base-commit: b2fe3a449cb5d130ea2fec65bb214601826cdeff -- 2.25.4