gbranden pushed a commit to branch master
in repository groff.
commit 86a4c9bbe490e6bfdb12c43bb85d249dd29edfae
Author: G. Branden Robinson <[email protected]>
AuthorDate: Fri May 16 19:49:33 2025 -0500
[groff]: Fix Savannah #67133 (BUILD FAILS).
Fail when piped command gets a SIGPIPE signal.
* src/roff/groff/pipeline.c (run_pipeline) [!_WIN32 && !__MSDOS__ &&
!_UWIN && !__CYGWIN__ && !__EMX__]: _Unconditionally_ set bit 2 of the
return value in the event of _any_ signal hitting a pipelined
process. A workaround that James Clark put in for a SunOS 4.1.1
X11-related bug in groff 1.06 (1992) appears to have led us to grief;
if any of the child processes in the pipeline being wait(2)ed on was
signaled with SIGPIPE, this alteration of return the value was not
being done. If that child was the last in the pipeline (gxditview,
the code presumes), he walks the list of commands in the pipeline and
kill(2)s them all with SIGPIPE. If a process has multiple fatal
signals pending, which one wins? Apparently, on Linux 5.10, in a
fight between SIGPIPE and SIGABRT (raised by abort(3), called by
assert(3)), SIGPIPE always wins. So bit 2 of this function's return
value, which (after a left shift) ultimately becomes groff(1)'s exit
status, never got set, and so groff happily reported success when it
should have screamed hideously of failure. Likely the SunOS 4
workaround should be ripped out entirely, but this fix adequately
detects grohtml failures.
Fixes <https://savannah.gnu.org/bugs/?67133>. Problem appears to date
back to groff 1.06 (1992).
I experimentally instrumented "pipeline.c" a bit, which helped me track
down the issue. The following was as good as a smoking gun to me.
GBR: Unix run_pipeline()
GBR: PID 54503 caught signal 13
GBR: run_pipeline() returning 0
---
ChangeLog | 28 ++++++++++++++++++++++++++++
src/roff/groff/pipeline.c | 8 +++-----
2 files changed, 31 insertions(+), 5 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index bfa19df08..4af839f7d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,31 @@
+2025-05-16 G. Branden Robinson <[email protected]>
+
+ [groff]: Fix Savannah #67133; fail when piped command gets a
+ SIGPIPE signal.
+
+ * src/roff/groff/pipeline.c (run_pipeline) [!_WIN32 &&
+ !__MSDOS__ && !_UWIN && !__CYGWIN__ && !__EMX__]:
+ _Unconditionally_ set bit 2 of the return value in the event of
+ _any_ signal hitting a pipelined process. A workaround that
+ James Clark put in for a SunOS 4.1.1 X11-related bug in groff
+ 1.06 (1992) appears to have led us to grief; if any of the child
+ processes in the pipeline being wait(2)ed on was signaled with
+ SIGPIPE, this alteration of the return value was not being done.
+ If that child was the last in the pipeline (gxditview, the code
+ presumes), he walks the list of commands in the pipeline and
+ kill(2)s them all with SIGPIPE. If a process has multiple fatal
+ signals pending, which one wins? Apparently, on Linux 5.10, in
+ a fight between SIGPIPE and SIGABRT (raised by abort(3), called
+ by assert(3)), SIGPIPE always wins. So bit 2 of this function's
+ return value, which (after a left shift) ultimately becomes
+ groff(1)'s exit status, never got set, and so groff happily
+ reported success when it should have screamed hideously of
+ failure. Likely the SunOS 4 workaround should be ripped out
+ entirely, but this fix adequately detects grohtml failures.
+
+ Fixes <https://savannah.gnu.org/bugs/?67133>. Problem appears
+ to date back to groff 1.06 (1992).
+
2025-05-16 G. Branden Robinson <[email protected]>
Make build more sensitive to failure of HTML output.
diff --git a/src/roff/groff/pipeline.c b/src/roff/groff/pipeline.c
index df4a85e98..08a1c486d 100644
--- a/src/roff/groff/pipeline.c
+++ b/src/roff/groff/pipeline.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1989-2024 Free Software Foundation, Inc.
+/* Copyright (C) 1989-2025 Free Software Foundation, Inc.
Written by James Clark ([email protected])
This file is part of groff.
@@ -327,7 +327,7 @@ int run_pipeline(int ncommands, char ***commands, bool
no_pipe)
return ret;
}
-#else /* not _WIN32 */
+#else /* not _WIN32 but __MSDOS__, _UWIN, __CYWGIN__, or __EMX__ */
/* MS-DOS doesn't have 'fork', so we need to simulate the pipe by
running the programs in sequence with standard streams redirected to
@@ -497,6 +497,7 @@ int run_pipeline(int ncommands, char ***commands, bool
no_pipe)
pids[i] = -1;
--proc_count;
if (WIFSIGNALED(status)) {
+ ret |= 2;
int sig = WTERMSIG(status);
#ifdef SIGPIPE
if (sig == SIGPIPE) {
@@ -518,13 +519,10 @@ int run_pipeline(int ncommands, char ***commands, bool
no_pipe)
}
else
#endif /* SIGPIPE */
- {
c_error("%1: %2%3",
commands[i][0],
strsignal(sig),
WCOREDUMP(status) ? " (core dumped)" : "");
- ret |= 2;
- }
}
else if (WIFEXITED(status)) {
int exit_status = WEXITSTATUS(status);
_______________________________________________
groff-commit mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/groff-commit