gbranden pushed a commit to branch master
in repository groff.
commit b62f0605427caa156f23c81280f345496dd8a5cc
Author: G. Branden Robinson <[email protected]>
AuthorDate: Thu Sep 26 17:26:16 2024 -0500
[pdfmom]: Handle errors and abnormal exits.
* src/devices/gropdf/pdfmom.pl: Handle signaled and error exits from
groff pipeline. Improve diagnostics. Store "basename" of executing
command into `prog` scalar. Gather the wait status returned by every
use of `system()`.
(abort): New subroutine writes a fatal diagnostic message and
exits with status 1.
(autopsy): New subroutine decodes a POSIX wait status to
determine the fate of an unlucky process, and returns it as a
human-readable string scalar. (The interesting part is cribbed
from Perl documentation.)
Also discard trailing whitespace from lines. Also update Vim modeline
to reflect indentation practice in evidence.
I managed to introduce a SEGV into tbl (that didn't show up with simple
inputs) in my working copy. To my dismay, the build just kept right on
trucking after failing to build "groff-man-pages.pdf", because pdfmom
ignored the return value of `system()`, concealing errors. I don't
think we can accept that; we need to fail fast and fail hard. If I
hadn't noticed the piteous "Segmentation fault" error scroll by, I might
have overlooked my mistake for a long time.
---
ChangeLog | 15 +++++++++++
src/devices/gropdf/pdfmom.pl | 64 ++++++++++++++++++++++++++++++++++----------
2 files changed, 65 insertions(+), 14 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index a192af200..b31b3831f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2024-09-26 G. Branden Robinson <[email protected]>
+
+ [pdfmom]: Handle errors and abnormal exits.
+
+ * src/devices/gropdf/pdfmom.pl: Handle signaled and error exits
+ from groff pipeline. Improve diagnostics. Store "basename" of
+ executing command into `prog` scalar. Gather the wait status
+ returned by every use of `system()`.
+ (abort): New subroutine writes a fatal diagnostic message and
+ exits with status 1.
+ (autopsy): New subroutine decodes a POSIX wait status to
+ determine the fate of an unlucky process, and returns it as a
+ human-readable string scalar. (The interesting part is cribbed
+ from Perl documentation.)
+
2024-09-26 G. Branden Robinson <[email protected]>
* src/preproc/tbl/table.cpp (table::add_entry): Throw warnings
diff --git a/src/devices/gropdf/pdfmom.pl b/src/devices/gropdf/pdfmom.pl
index a8117a56a..5806fba9b 100644
--- a/src/devices/gropdf/pdfmom.pl
+++ b/src/devices/gropdf/pdfmom.pl
@@ -4,7 +4,7 @@
# Deri James : Friday 16 Mar 2012
#
-# Copyright (C) 2012-2020 Free Software Foundation, Inc.
+# Copyright (C) 2012-2024 Free Software Foundation, Inc.
# Written by Deri James <[email protected]>
#
# This file is part of groff.
@@ -24,7 +24,9 @@
use strict;
use warnings;
+use File::Spec qw/splitpath/;
use File::Temp qw/tempfile/;
+
my @cmd;
my $dev='pdf';
my $preconv='';
@@ -48,10 +50,38 @@ my $RT_SEP='@RT_SEP@';
$ENV{PATH}=$ENV{GROFF_BIN_PATH}.$RT_SEP.$ENV{PATH} if
exists($ENV{GROFF_BIN_PATH});
$ENV{TMPDIR}=$ENV{GROFF_TMPDIR} if exists($ENV{GROFF_TMPDIR});
+(undef,undef,my $prog)=File::Spec->splitpath($0);
+
+sub abort
+{
+ my $message=shift(@_);
+ print STDERR "$prog: fatal error: $message";
+ exit 1;
+}
+
+sub autopsy
+{
+ my $waitstatus=shift(@_);
+ my $finding;
+
+ if ($waitstatus == -1) {
+ $finding = "unable to run groff: $!\n";
+ }
+ elsif ($? & 127) {
+ $finding = sprintf("groff died with signal %d, %s core dump\n",
+ ($? & 127), ($? & 128) ? 'with' : 'without');
+ }
+ else {
+ $finding = sprintf("groff exited with status %d\n", $? >> 8);
+ }
+
+ return $finding;
+}
+
while (my $c=shift)
{
$c=~s/(?<!\\)"/\\"/g;
-
+
if (substr($c,0,2) eq '-T')
{
if (length($c) > 2)
@@ -122,7 +152,7 @@ while (my $c=shift)
else
{
# Just a '-'
-
+
push(@cmd,$c);
$readstdin=2;
}
@@ -130,10 +160,10 @@ while (my $c=shift)
else
{
# Got a filename?
-
+
push(@cmd,"\"$c\"");
$readstdin=0 if $readstdin == 1;
-
+
}
}
@@ -148,40 +178,46 @@ if ($readstdin)
{
print $fh ($_);
}
-
+
close($fh);
-
+
$cmdstring=~s/ - / $tmpfn / if $readstdin == 2;
$cmdstring.=" $tmpfn " if $readstdin == 1;
}
+my $waitstatus = 0;
+
if ($dev eq 'pdf')
{
if ($mom)
{
- system("groff -Tpdf -dLABEL.REFS=1 $mom -z $cmdstring 2>&1 | LC_ALL=C
grep '^\\. *ds' | groff -Tpdf $preconv -dPDF.EXPORT=1 -dLABEL.REFS=1 $mom -z -
$cmdstring 2>&1 | LC_ALL=C grep '^\\. *ds' | groff -Tpdf $mom $preconv -
$cmdstring $zflg");
+ $waitstatus = system("groff -Tpdf -dLABEL.REFS=1 $mom -z $cmdstring
2>&1 | LC_ALL=C grep '^\\. *ds' | groff -Tpdf $preconv -dPDF.EXPORT=1
-dLABEL.REFS=1 $mom -z - $cmdstring 2>&1 | LC_ALL=C grep '^\\. *ds' | groff
-Tpdf $mom $preconv - $cmdstring $zflg");
+ abort(autopsy($?)) unless $waitstatus == 0;
+
}
else
{
- system("groff -Tpdf $preconv -dPDF.EXPORT=1 -z $cmdstring 2>&1 |
LC_ALL=C grep '^\\. *ds' | groff -Tpdf $preconv - $cmdstring $zflg");
+ $waitstatus = system("groff -Tpdf $preconv -dPDF.EXPORT=1 -z $cmdstring
2>&1 | LC_ALL=C grep '^\\. *ds' | groff -Tpdf $preconv - $cmdstring $zflg");
+ abort(autopsy($?)) unless $waitstatus == 0;
}
}
elsif ($dev eq 'ps')
{
- system("groff -Tpdf -dLABEL.REFS=1 $mom -z $cmdstring 2>&1 | LC_ALL=C grep
'^\\. *ds' | pdfroff -mpdfmark $mom --no-toc - $preconv $cmdstring");
+ $waitstatus = system("groff -Tpdf -dLABEL.REFS=1 $mom -z $cmdstring
2>&1 | LC_ALL=C grep '^\\. *ds' | pdfroff -mpdfmark $mom --no-toc - $preconv
$cmdstring");
+ abort(autopsy($?)) unless $waitstatus == 0;
}
elsif ($dev eq '-z') # pseudo dev - just compile for warnings
{
- system("groff -Tpdf $mom -z $cmdstring");
+ $waitstatus = system("groff -Tpdf $mom -z $cmdstring");
+ abort(autopsy($?)) unless $waitstatus == 0;
}
else
{
- print STDERR "Not compatible with device '-T $dev'\n";
- exit 1;
+ abort("groff output device '$dev' not supported");
}
# Local Variables:
# fill-column: 72
# mode: CPerl
# End:
-# vim: set cindent noexpandtab shiftwidth=2 softtabstop=2 textwidth=72:
+# vim: set cindent noexpandtab shiftwidth=4 softtabstop=4 textwidth=72:
_______________________________________________
Groff-commit mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/groff-commit