zgrep: terminate gracefully when a pipeline is interrupted by a signal
authorDmitry V. Levin <ldv@altlinux.org>
Sat, 30 Jan 2010 22:36:35 +0000 (22:36 +0000)
committerJim Meyering <meyering@redhat.com>
Thu, 4 Feb 2010 06:16:11 +0000 (07:16 +0100)
zgrep is not terminated gracefully when its grep/sed pipeline
is terminated by a signal.  For example, a command like
zgrep -F .TH /usr/share/man/man1/*.gz | head
continues working long after the "head" process completes.
Another example, a command like
zgrep unmatched-pattern /usr/share/man/man1/*.gz
cannot be interrupted by sending a SIGQUIT with Ctrl-\ key, it outputs
zgrep: line 221: test: : integer expression expected
and goes on.
* zgrep.in: Terminate gracefully when the grep/sed pipeline is
terminated by a signal.
* tests/zgrep-signal: New test.
* Makefile.am (TESTS): Add it.

Makefile.am
tests/zgrep-signal [new file with mode: 0644]
zgrep.in

index 4263b1d757c889c3b236ae36e2b7f4b2a060b03f..19ef05157eeb01423cb63ac7c3f7f8d5c6d7e72d 100644 (file)
@@ -110,6 +110,7 @@ TESTS =                                             \
   tests/trailing-nul                           \
   tests/zdiff                                  \
   tests/zgrep-f                                        \
+  tests/zgrep-signal                           \
   tests/znew-k
 
 EXTRA_DIST += $(TESTS)
diff --git a/tests/zgrep-signal b/tests/zgrep-signal
new file mode 100644 (file)
index 0000000..4acd737
--- /dev/null
@@ -0,0 +1,38 @@
+#!/bin/sh
+# Check that zgrep is terminated gracefully by signal when
+# its grep/sed pipeline is terminated by a signal.
+
+# Copyright (C) 2010 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/>.
+# limit so don't run it by default.
+
+if test "$VERBOSE" = yes; then
+  set -x
+  gzip --version
+fi
+
+: ${srcdir=.}
+. "$srcdir/tests/init.sh"
+
+echo a | gzip -c > f.gz || framework_failure
+
+fail=0
+
+status=$(exec 3>&1; (zgrep a f.gz f.gz; echo $? >&3) | :) ||
+         framework_failure
+
+test "$status" = 141 || fail=1
+
+Exit $fail
index 358c1f8dc8a89841f4baa497acb657ab1bd75b26..5d9e6d10f7f1a193cc22a5305407049ab6c12d49 100644 (file)
--- a/zgrep.in
+++ b/zgrep.in
@@ -213,11 +213,16 @@ do
       r=$(
         exec 4>&1
         (eval "$grep" 4>&-; echo $? >&4) 3>&- | sed "$sed_script" >&3 4>&-
-      ) || r=2
-      exit $r
+      ) && exit $r
+      r=$?
+      test $r -gt 128 && test $r -le 143 && exit $r || exit 2
     fi >&3 5>&-
   )
   r=$?
+  if test $r -gt 128 && test $r -le 143; then
+    kill -$(($r-128)) $$
+    exit $r
+  fi
   test "$gzip_status" -eq 0 || test "$gzip_status" -eq 2 || r=2
   test $res -lt $r && res=$r
 done