From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id 0TgcNedmzmoMIAMAWB0awg (envelope-from ) for ; Tue, 13 Oct 2026 13:14:15 -0400 Received: by simark.ca (Postfix, from userid 112) id D216F1E051; Tue, 13 Oct 2026 13:14:15 -0400 (EDT) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-5.3 required=5.0 tests=ARC_SIGNED,ARC_VALID,BAYES_00, 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 8B68D1E04E for ; Tue, 13 Oct 2026 13:14:14 -0400 (EDT) Received: from vm01.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id D64594BA23D3 for ; Tue, 13 Oct 2026 17:14:13 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org D64594BA23D3 Received: from simark.ca (simark.ca [158.69.221.121]) by sourceware.org (Postfix) with ESMTPS id DC4044BA798C for ; Tue, 13 Oct 2026 17:13:45 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org DC4044BA798C Authentication-Results: sourceware.org; dmarc=fail (p=none dis=none) header.from=efficios.com Authentication-Results: sourceware.org; spf=fail smtp.mailfrom=efficios.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org DC4044BA798C Authentication-Results: sourceware.org; arc=none smtp.remote-ip=158.69.221.121 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1791911625; cv=none; b=Af5IQqhUDryxJZgO8QBJU2ePsMjC6xIePzZcJkB5sH2a49auY5Z+l7g/2QncqTSYPNZitGe81Vxd42TfxDtOwgeNbmo/BgcAL5jBhSRHZsBfatkhES/llNp1b8JIeBm4xhxkKCdJjhBb/UyFDnEU77w7nWsiF6aSUEpiPfvKBSk= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1791911625; c=relaxed/simple; bh=sPd0wFw6xMkbXEmXNxDQf+RLR0Qgu7E9i+sNCjr+QEc=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=uSaHgcEjDd5NzCDDkdzHUktBC6UsL8S7dNjVPViZchKvYPNRIaIibsCPwNmt4B7vv89KUzTCABFzuPxzbz3trlO8eMCtI/iTN9dzBs2IoHwtyVhLblfevavFWguKV7MFCMstYHhJcR8hdgmmbvq2J46mcZqX6UZZeEQ5hqVLW4E= ARC-Authentication-Results: i=1; sourceware.org Received: by simark.ca (Postfix) id D5CB01E050; Tue, 13 Oct 2026 13:13:43 -0400 (EDT) From: Simon Marchi To: gdb-patches@sourceware.org Cc: Simon Marchi Subject: [PATCH 2/2] gdb: preserve shell command exit status in pipe command on EPIPE Date: Tue, 13 Oct 2026 13:13:31 -0400 Message-ID: <20261013171340.1748775-2-simon.marchi@efficios.com> X-Mailer: git-send-email 2.56.0 In-Reply-To: <20261013171340.1748775-1-simon.marchi@efficios.com> References: <20261013171340.1748775-1-simon.marchi@efficios.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 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 When the shell command of the pipe command exits without reading all of its input, the pipe command may fail with: (gdb) pipe COMMAND | head -1 ... shell command "head -1" failed: Broken pipe pclose flushes the buffered output before closing the stream. If that flush fails, pclose may return -1 (with errno == EPIPE) instead of the exit status of the shell command. Work around this by flusing the stream explicitly before calling pclose, ignoring errors. With that out of the way, pclose returns the exit status of the shell command. This makes something like "pipe COMMAND | head -1" behave like it would in a shell. Update the test added in the previous commit to check the exit status of the shell commands. Change-Id: I939e4610f6c09ac2007a0c58f64480106c74edb2 --- gdb/cli/cli-cmds.c | 9 ++++++++- gdb/testsuite/gdb.base/shell.exp | 17 +++++++++++++---- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c index bb7a7acbc3ac..7aca84ff09ac 100644 --- a/gdb/cli/cli-cmds.c +++ b/gdb/cli/cli-cmds.c @@ -1171,7 +1171,14 @@ pipe_command (const char *arg, int from_tty) since that is done during Python initialization. */ scoped_ignore_sigpipe ignore_sigpipe; - SCOPE_EXIT { exit_status = pclose (to_shell_command); }; + SCOPE_EXIT + { + /* Flush explicitly, ignoring errors, so that a failure to write + buffered output (for instance, with EPIPE) doesn't make pclose fail + and hide the exit status of the shell command. */ + fflush (to_shell_command); + exit_status = pclose (to_shell_command); + }; stdio_file pipe_file (to_shell_command); diff --git a/gdb/testsuite/gdb.base/shell.exp b/gdb/testsuite/gdb.base/shell.exp index 272ce070ce1a..2e6c63585eb0 100644 --- a/gdb/testsuite/gdb.base/shell.exp +++ b/gdb/testsuite/gdb.base/shell.exp @@ -199,7 +199,8 @@ foreach cmd {"pipe " "| " "|"} { # Test piping a lot of output to a shell command that exits without # reading its input. The output is larger than the pipe buffer, so GDB # necessarily writes to the pipe after the shell command has exited, -# regardless of timing. GDB must not get killed by SIGPIPE. +# regardless of timing. GDB must not get killed by SIGPIPE, and must +# report the exit status of the shell command. proc_with_prefix test_pipe_reader_exits_early {} { clean_restart @@ -223,9 +224,17 @@ proc_with_prefix test_pipe_reader_exits_early {} { {set $i = $i + 1} \ {end}] - gdb_test "pipe lots | exit 0" - gdb_test "pipe lots | exit 1" - gdb_test "pipe lots | head -1" + gdb_test_no_output "pipe lots | exit 0" + gdb_test "p \$_shell_exitcode" " = 0" "exit 0 exitcode" + gdb_test "p \$_shell_exitsignal" " = void" "exit 0 exitsignal" + + gdb_test_no_output "pipe lots | exit 1" + gdb_test "p \$_shell_exitcode" " = 1" "exit 1 exitcode" + gdb_test "p \$_shell_exitsignal" " = void" "exit 1 exitsignal" + + gdb_test "pipe lots | head -1" "^$line" + gdb_test "p \$_shell_exitcode" " = 0" "head -1 exitcode" + gdb_test "p \$_shell_exitsignal" " = void" "head -1 exitsignal" } test_pipe_reader_exits_early -- 2.56.0