From 9858f29e6a9ebc02a70e6e31d54404f13fbf4b10 Mon Sep 17 00:00:00 2001 From: Tom de Vries Date: Tue, 22 Oct 2024 08:53:51 +0200 Subject: [PATCH] [gdb] Handle EINTR in run_under_shell When building gdb with -O2 -fsanitize=thread and running test-case gdb.base/bg-exec-sigint-bp-cond.exp, I run into: ... (gdb) c&^M Continuing.^M (gdb) Quit^M (gdb) quit_count=1 ^M Breakpoint 2, foo () at bg-exec-sigint-bp-cond.c:23^M 23 return 0;^M FAIL: $exp: no force memory write: \ SIGINT does not interrupt background execution ... What happens is that: - the breakpoint hits - while evaluating the condition of the breakpoint, $_shell("kill -INT ") is called, handled by run_under_shell - in run_under_shell, a vfork is issued - in the vfork child, execl executes the kill command - in the vfork parent, waitpid is called to wait for the result of the kill command - waitpid returns -1 with errno set to EINTR - run_under_shell doesn't check the result of waitpid, and returns the value of local variable status. Since waitpid returned -1, status was not assigned a value, so it's uninitialized, and happens to be non-zero - the breakpoint condition evaluates to true, because $_shell("kill -INT ") != 0 - the breakpoint triggers a stop, which the test-case doesn't expect. Fix this by using gdb::handle_eintr to call waitpid in run_under_shell. Also handle the case that waitpid returns an error other than EINTR, using perror_with_name. Tested on x86_64-linux. Approved-By: Tom Tromey PR gdb/30695 Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30695 --- gdb/cli/cli-cmds.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c index ea2e156a00c..65ac7d6e7fb 100644 --- a/gdb/cli/cli-cmds.c +++ b/gdb/cli/cli-cmds.c @@ -55,6 +55,7 @@ #include "extension.h" #include "gdbsupport/pathstuff.h" #include "gdbsupport/gdb_tilde_expand.h" +#include "gdbsupport/eintr.h" #ifdef TUI #include "tui/tui.h" @@ -921,7 +922,11 @@ run_under_shell (const char *arg, int from_tty) } if (pid != -1) - waitpid (pid, &status, 0); + { + int ret = gdb::handle_eintr (-1, ::waitpid, pid, &status, 0); + if (ret == -1) + perror_with_name ("Cannot get status of shell command"); + } else error (_("Fork failed")); return status; -- 2.39.5