coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH 1/4] grep: don't say "write error" over and over


From: Eric Blake
Subject: Re: [PATCH 1/4] grep: don't say "write error" over and over
Date: Wed, 08 Feb 2012 10:18:58 -0700
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:10.0) Gecko/20120131 Thunderbird/10.0

[adding coreutils]

On 02/07/2012 11:21 PM, Paul Eggert wrote:
> On 01/20/2012 11:06 PM, Paul Eggert wrote:
>> I took a look and came up with four related patches to fix these.
>> Here's the first one.  It fixes the originally-reported bug.
> 
> I found a problem in that patch's test case: it assumes
> that SIGPIPE has the default action when the test is
> run, which isn't a portable assumption.  I installed the
> following further patch to fix this bug in the test case.

Alas, you _cannot_ use trap to undo a shell that is started with SIGPIPE
ignored.  POSIX requires that:

"Signals that were ignored on entry to a non-interactive shell cannot be
trapped or reset, although no error need be reported when attempting to
do so."

http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#trap

$ (trap '' PIPE; bash -c 'trap; trap - PIPE; trap')
trap -- '' SIGPIPE
trap -- '' SIGPIPE

Even more interesting, ksh refuses to tell you that it is ignoring a
trap, until you try to change it:

$ (trap '' PIPE; ksh -c 'trap; echo 0; trap "echo 1" PIPE; trap; \
     echo 2; kill -s PIPE $$; trap; echo 3')
0
trap -- '' PIPE
2
trap -- '' PIPE
3

Then there is dash, which obeys POSIX on ignoring changes to the trap,
but fails to inform you (I'm filing a bug against dash, as that is just
outright mean to lie):

$ (trap '' PIPE; dash -c 'trap; echo 0; trap "echo 1" PIPE; trap; \
     echo 2; kill -s PIPE $$; trap; echo 3')
0
trap -- 'echo 1' PIPE
2
trap -- 'echo 1' PIPE
3

> 
> tests: work even if SIGPIPE is ignored
> * tests/epipe: Do not infinite-loop if SIGPIPE is already ignored.
> It could be that the invoker of 'make check' ignores SIGPIPE,
> for example.
> diff --git a/tests/epipe b/tests/epipe
> index 336d994..f9cb3f6 100755
> --- a/tests/epipe
> +++ b/tests/epipe
> @@ -6,7 +6,7 @@
> 
>  if
>     (
> -     while :; do echo x; done |
> +     (trap - PIPE; while echo x; do :; done) 3>&- |

So this won't work reliably, and can still inf-loop if epipe is executed
from an environment with SIGPIPE ignored.

The _only_ way to reset SIGPIPE out of not being ignored is to execute
an intermediary program that doesn't share the shell's lame POSIX
restriction.

I almost wonder if coreutils should add a way to reset signals, perhaps
as a new option to env, as in:

env --reset-signal=PIPE echo x

Obviously, if we add that extension to coreutils, you'd have to mark
this particular grep test as skipped on platforms that lack env
--reset-signal, and where we can detect either detect that SIGPIPE is
ignored by the shell, or where we can detect that the shell is not know
for its ability to tell us the truth about whether SIGPIPE is ignored.

-- 
Eric Blake   address@hidden    +1-919-301-3266
Libvirt virtualization library http://libvirt.org

Attachment: signature.asc
Description: OpenPGP digital signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]