Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [PATCH 1/1] gdb: use waitpid directly in wait_to_die_with_timeout
@ 2026-04-20 13:12 Abdul Basit Ijaz
  2026-04-28 15:37 ` Tom Tromey
  0 siblings, 1 reply; 2+ messages in thread
From: Abdul Basit Ijaz @ 2026-04-20 13:12 UTC (permalink / raw)
  To: gdb-patches; +Cc: tankut.baris.aktemur, abdul.b.ijaz

Suppose we have a gdbserver target connected to GDB via a serial pipe.
Also suppose the inferior is a long- or infinitely-running process
launched by gdbserver.  E.g. like this:

  (gdb) target remote | gdbserver - infinite.out

If we use the 'detach' command, there is a hang:

  (gdb) detach
  Detaching from program: target:/tmp/infinite.out, process 308481
  Detaching from process 308481
  Ending remote debugging.
  Ignoring packet error, continuing...
  [Inferior 1 (process 308481) detached]
  >>> HANG <<<

This is a regression since commit "[gdb] Use gdb::waitpid more often",
before which GDB was giving the prompt after a timeout.  The reason is
in wait_to_die_with_timeout GDB calls gdb::waitpid to wait for
gdbserver with an interrupt timeout set by an alarm call.  In
gdb::waitpid, we call gdb::handle_eintr, which repeatedly makes the
syscall if it's interrupted.  In this case, however, we wouldn't want
to repeat the waitpid if the timeout expired.  Hence, go back to using
waitpid directly, instead of gdb::waitpid, to restore the previous
behavior.

A regression-test is included.

One may wonder why gdbserver does not terminate and the timeout
expires.  The reason is, 'detach' command makes gdbserver detach from
the process as the debugger, which resumes the debuggee process.  If
that process was launched by gdbserver instead of having been attached
and if the process runs indefinitely long, gdbserver also waits
indefinitely.  From gdbserver/server.cc:

          /* If we are attached, then we can exit.  Otherwise, we
             need to hang around doing nothing, until the child is
             gone.  */
          join_inferior (pid);
          exit (0);

This indefinite wait causes the timeout with EINTR in waitpid call at
the GDB side inside wait_to_die_with_timeout.

Co-authored-by: Tankut Baris Aktemur <tankut.baris.aktemur@intel.com>
---
 gdb/testsuite/gdb.server/server-pipe-hang.c   | 33 +++++++++++++
 gdb/testsuite/gdb.server/server-pipe-hang.exp | 49 +++++++++++++++++++
 gdb/utils.c                                   |  5 +-
 3 files changed, 86 insertions(+), 1 deletion(-)
 create mode 100644 gdb/testsuite/gdb.server/server-pipe-hang.c
 create mode 100644 gdb/testsuite/gdb.server/server-pipe-hang.exp

diff --git a/gdb/testsuite/gdb.server/server-pipe-hang.c b/gdb/testsuite/gdb.server/server-pipe-hang.c
new file mode 100644
index 00000000000..c9e5bc4051d
--- /dev/null
+++ b/gdb/testsuite/gdb.server/server-pipe-hang.c
@@ -0,0 +1,33 @@
+/* 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 <http://www.gnu.org/licenses/>.  */
+
+/* This program is intended to be started for the target using pipe command
+   inside GDB and then it loops.  */
+
+#include <unistd.h>
+
+int
+main (void)
+{
+  /* Prevent an infinite run.  */
+  alarm (60);
+
+  while (1)
+    sleep (5);
+
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.server/server-pipe-hang.exp b/gdb/testsuite/gdb.server/server-pipe-hang.exp
new file mode 100644
index 00000000000..50815bfaefc
--- /dev/null
+++ b/gdb/testsuite/gdb.server/server-pipe-hang.exp
@@ -0,0 +1,49 @@
+# 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/>.
+
+# This test relies on starting gdbserver using the pipe syntax.  Afterwards
+# it checks if "detach" command does not hang.
+
+# Test is aimed at starting with the native target only.
+# We manually create a pipe connection to a gdbserver below.
+require gdb_protocol_is_native
+
+load_lib gdbserver-support.exp
+
+standard_testfile
+
+require allow_gdbserver_tests
+
+set gdbserver [find_gdbserver]
+if { $gdbserver == "" } {
+    unsupported "could not find gdbserver"
+    return
+}
+
+if {[build_executable "failed to prepare" $testfile $srcfile debug]} {
+    return
+}
+
+clean_restart
+
+gdb_test "target remote | ${::gdbserver} - ${::binfile}" ".*" \
+    "start gdbserver using pipe syntax"
+
+# The 5 seconds alarm in wait_to_die_with_timeout should make us get
+# the prompt.
+save_vars timeout {
+    set timeout 30
+    gdb_test "detach" ".*" "detached without hang"
+}
diff --git a/gdb/utils.c b/gdb/utils.c
index f5f19301460..e37e37797dd 100644
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -3478,7 +3478,10 @@ wait_to_die_with_timeout (pid_t pid, int *status, int timeout)
       alarm (timeout);
 #endif
 
-      waitpid_result = gdb::waitpid (pid, status, 0);
+      /* Do not use gdb::waitpid here.  We want to interrupt the
+	 syscall with SIGALRM above to prevent waiting forever, and if
+	 that interrupt happens, we don't want to repeat.  */
+      waitpid_result = waitpid (pid, status, 0);
 
 #ifdef SIGALRM
       alarm (0);
-- 
2.34.1

Intel Deutschland GmbH
Registered Address: Dornacher Strasse 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 Muenchen HRB 186928


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH 1/1] gdb: use waitpid directly in wait_to_die_with_timeout
  2026-04-20 13:12 [PATCH 1/1] gdb: use waitpid directly in wait_to_die_with_timeout Abdul Basit Ijaz
@ 2026-04-28 15:37 ` Tom Tromey
  0 siblings, 0 replies; 2+ messages in thread
From: Tom Tromey @ 2026-04-28 15:37 UTC (permalink / raw)
  To: Abdul Basit Ijaz; +Cc: gdb-patches, tankut.baris.aktemur

>>>>> Abdul Basit Ijaz <abdul.b.ijaz@intel.com> writes:

> This is a regression since commit "[gdb] Use gdb::waitpid more often",
> before which GDB was giving the prompt after a timeout.  The reason is
> in wait_to_die_with_timeout GDB calls gdb::waitpid to wait for
> gdbserver with an interrupt timeout set by an alarm call.  In
> gdb::waitpid, we call gdb::handle_eintr, which repeatedly makes the
> syscall if it's interrupted.  In this case, however, we wouldn't want
> to repeat the waitpid if the timeout expired.  Hence, go back to using
> waitpid directly, instead of gdb::waitpid, to restore the previous
> behavior.

Makes sense.  Thanks.
Approved-By: Tom Tromey <tom@tromey.com>

Tom

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-04-28 15:38 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-04-20 13:12 [PATCH 1/1] gdb: use waitpid directly in wait_to_die_with_timeout Abdul Basit Ijaz
2026-04-28 15:37 ` Tom Tromey

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox