On Fri, Apr 4, 2014 at 2:12 PM, Philip Guenther <guent...@gmail.com> wrote:
> On Fri, Apr 4, 2014 at 11:27 AM, Marco Pfatschbacher <m...@mailq.de> wrote:
>> On Thu, Apr 03, 2014 at 05:19:45PM -0600, Theo de Raadt wrote:
>>> Interesting.  Can we take bath approaches?
>>
>> I don't see why we should not.
>>
>>> Is there a reason to not expose either error?
>>
>> I thought it might break some legacy stuff regarding
>> tapes and such. But since no one spoke up...
>>
>> OK?
>>
>>> > pax does not exit with an error if the processed
>>> > archive is truncated:
>>> >
>>> > # (cd / && tar zcf - bsd | dd count=128 2>/dev/null | tar tzf -)
>>> > bsd
>>> > gzip: stdin: Input/output error
>>> > tar: End of archive volume 1 reached
>>> > gzip: stdout: Broken pipe
>>> > tar: Failed write to archive volume: 1: Broken pipe
>>> > # echo $?
>>> > 0
>>> >
>>> >
>>> > There's two ways to fix this.
>>> > 1) take the exit code of gzip into account:
>>> >
>>> > Index: ar_io.c
>>> > ===================================================================
>>> > RCS file: /cvs/src/bin/pax/ar_io.c,v
>>> > retrieving revision 1.44
>>> > diff -u -p -p -u -r1.44 ar_io.c
>>> > --- ar_io.c 11 Jan 2014 05:36:26 -0000      1.44
>>> > +++ ar_io.c 28 Mar 2014 14:09:37 -0000
>>> > @@ -337,8 +337,11 @@ ar_close(void)
>>> >     (void)close(arfd);
>>> >
>>> >     /* Do not exit before child to ensure data integrity */
>>> > -   if (zpid > 0)
>>> > +   if (zpid > 0) {
>>> >             waitpid(zpid, &status, 0);
>>> > +           if (WIFEXITED(status) && WEXITSTATUS(status))
>>> > +                   exit_val = 1;
>>> > +   }
>
> Hmm, should that be
>     if (!WIFEXITED(status) || WEXITSTATUS(status))

This is incorrect because a process can conclude its work before
terminating because of a signal.

To demonstrate I can use the OP's pipeline:

for i in $(jot 100); do
        { cd /; tar czf - bsd & p=$!; sleep 0.8; kill $p; } | tar tzf -
        echo X
done 2>&1 |
    awk '/^X/ {a[FNR - c - 1]++;  c = FNR} END {print "complete write "a[1]
                                                print "late signal    "a[2]
                                                print "short write    "a[4]}'

complete write 8  # concluded work, terminated by signal
late signal    34 # concluded work, beat the signal race
short write    58 # terminated by signal before concluding work

This is only an example. Like other processes, gzip is subject to the race.

Reply via email to