Re: [PATCH] Re: SIGPIPE and tee

2019-10-07 Thread Sam Liddicott
Thanks - that change is great. Busybox tee now propagates SIGPIPE just like
GNU tee does by default.

Sam



On Mon, 7 Oct 2019 at 13:27, Denys Vlasenko 
wrote:

> On Fri, Oct 4, 2019 at 11:20 AM Sam Liddicott  wrote:
> > nudge on this attached patch
> >
> > -- Forwarded message -
> > From: Sam Liddicott 
> > Date: Fri, 13 Sep 2019 at 11:15
> > Subject: Re: SIGPIPE and tee
> > To: busybox 
> >
> >
> > Here is a patch which invokes kill_myself_with_sig(SIGPIPE) if fwrite
> fails with errno=EPIPE.
> >
> > Quitting with a signal rather than a diagnostic output emulates GNU tee
> which is in line with the apparent reason for busybox tee in ignoring
> SIGPIPE in the first place.
>
>
> >
> > I have tested it with and without CONFIG_FEATURE_TEE_USE_BLOCK_IO=y
> >
> > As expected, dd succeeds for bs=1024 with
> CONFIG_FEATURE_TEE_USE_BLOCK_IO=y but fails for without.
> > dd fails in both cases for bs=1024000
> > tee fails in both cases
> >
> > ( sleep 2 ; dd if=/dev/zero bs=1024000 count=5 ; echo dd $? > /dev/tty ;
> ) | {
> build_output/sysroots-components/x86_64/busybox-native/bin/busybox.nosuid
> tee /dev/null ; echo tee $? >/dev/tty ; } | sleep 1
> >
> > ( sleep 2 ; dd if=/dev/zero bs=1024 count=5 ; echo dd $? > /dev/tty ; )
> | {
> build_output/sysroots-components/x86_64/busybox-native/bin/busybox.nosuid
> tee /dev/null ; echo tee $? >/dev/tty ; } | sleep 1
> >
> > A colleague has suggested that any write failure to stdout by tee ought
> to cause tee to quit, but I leave this to your consideration; something
> like this might cover both cases but I haven't tested it:
> >
> > if (fwrite(buf, 1, c, *fp) != c) {
> >   if (errno == EPIPE) kill_myself_with_sig(SIGPIPE);
> >   retval = EXIT_FAILURE;
> >   break;
> > }
> >
> > Sam
> >
> >
> > On Thu, 12 Sep 2019 at 20:03, Sam Liddicott  wrote:
> >>
> >> In  https://git.busybox.net/busybox/tree/coreutils/tee.c we read:
> >>
> >> /* gnu tee ignores SIGPIPE in case one of the output files is a pipe
> >> * that doesn't consume all its input.  Good idea... */
> >> signal(SIGPIPE, SIG_IGN);
> >>
> >>
> >> Sadly, this breaks POSIX SIGPIPE behaviour with respect to quitting
> when stdout (as a pipe) is closed.
> >>
> >> Despite the comment, GNU tee does not behave as the comment suggests.
>
> Exactly. GNU tee does not intercept SIGPIPE (unless -p is given).
> I'm removing SIGPIPE handling.
> Please try current git.
>
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: [PATCH] Re: SIGPIPE and tee

2019-10-07 Thread Denys Vlasenko
On Fri, Oct 4, 2019 at 11:20 AM Sam Liddicott  wrote:
> nudge on this attached patch
>
> -- Forwarded message -
> From: Sam Liddicott 
> Date: Fri, 13 Sep 2019 at 11:15
> Subject: Re: SIGPIPE and tee
> To: busybox 
>
>
> Here is a patch which invokes kill_myself_with_sig(SIGPIPE) if fwrite fails 
> with errno=EPIPE.
>
> Quitting with a signal rather than a diagnostic output emulates GNU tee which 
> is in line with the apparent reason for busybox tee in ignoring SIGPIPE in 
> the first place.


>
> I have tested it with and without CONFIG_FEATURE_TEE_USE_BLOCK_IO=y
>
> As expected, dd succeeds for bs=1024 with CONFIG_FEATURE_TEE_USE_BLOCK_IO=y 
> but fails for without.
> dd fails in both cases for bs=1024000
> tee fails in both cases
>
> ( sleep 2 ; dd if=/dev/zero bs=1024000 count=5 ; echo dd $? > /dev/tty ; ) | 
> { build_output/sysroots-components/x86_64/busybox-native/bin/busybox.nosuid 
> tee /dev/null ; echo tee $? >/dev/tty ; } | sleep 1
>
> ( sleep 2 ; dd if=/dev/zero bs=1024 count=5 ; echo dd $? > /dev/tty ; ) | { 
> build_output/sysroots-components/x86_64/busybox-native/bin/busybox.nosuid tee 
> /dev/null ; echo tee $? >/dev/tty ; } | sleep 1
>
> A colleague has suggested that any write failure to stdout by tee ought to 
> cause tee to quit, but I leave this to your consideration; something like 
> this might cover both cases but I haven't tested it:
>
> if (fwrite(buf, 1, c, *fp) != c) {
>   if (errno == EPIPE) kill_myself_with_sig(SIGPIPE);
>   retval = EXIT_FAILURE;
>   break;
> }
>
> Sam
>
>
> On Thu, 12 Sep 2019 at 20:03, Sam Liddicott  wrote:
>>
>> In  https://git.busybox.net/busybox/tree/coreutils/tee.c we read:
>>
>> /* gnu tee ignores SIGPIPE in case one of the output files is a pipe
>> * that doesn't consume all its input.  Good idea... */
>> signal(SIGPIPE, SIG_IGN);
>>
>>
>> Sadly, this breaks POSIX SIGPIPE behaviour with respect to quitting when 
>> stdout (as a pipe) is closed.
>>
>> Despite the comment, GNU tee does not behave as the comment suggests.

Exactly. GNU tee does not intercept SIGPIPE (unless -p is given).
I'm removing SIGPIPE handling.
Please try current git.
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


[PATCH] Re: SIGPIPE and tee

2019-10-04 Thread Sam Liddicott
nudge on this attached patch

-- Forwarded message -
From: Sam Liddicott 
Date: Fri, 13 Sep 2019 at 11:15
Subject: Re: SIGPIPE and tee
To: busybox 


Here is a patch which invokes kill_myself_with_sig(SIGPIPE) if fwrite fails
with errno=EPIPE.

Quitting with a signal rather than a diagnostic output emulates GNU tee
which is in line with the apparent reason for busybox tee in ignoring
SIGPIPE in the first place.

I have tested it with and without CONFIG_FEATURE_TEE_USE_BLOCK_IO=y

As expected, dd succeeds for bs=1024 with CONFIG_FEATURE_TEE_USE_BLOCK_IO=y
but fails for without.
dd fails in both cases for bs=1024000
tee fails in both cases

( sleep 2 ; dd if=/dev/zero bs=1024000 count=5 ; echo dd $? > /dev/tty ; )
| {
build_output/sysroots-components/x86_64/busybox-native/bin/busybox.nosuid
tee /dev/null ; echo tee $? >/dev/tty ; } | sleep 1

( sleep 2 ; dd if=/dev/zero bs=1024 count=5 ; echo dd $? > /dev/tty ; ) | {
build_output/sysroots-components/x86_64/busybox-native/bin/busybox.nosuid
tee /dev/null ; echo tee $? >/dev/tty ; } | sleep 1

A colleague has suggested that *any* write failure to *stdout* by tee ought
to cause tee to quit, but I leave this to your consideration; something
like this *might* cover both cases but I haven't tested it:

if (fwrite(buf, 1, c, *fp) != c) {
  if (errno == EPIPE) kill_myself_with_sig(SIGPIPE);
  retval = EXIT_FAILURE;
  break;
}

Sam


On Thu, 12 Sep 2019 at 20:03, Sam Liddicott  wrote:

> In  https://git.busybox.net/busybox/tree/coreutils/tee.c we read:
>
>   /* gnu tee ignores SIGPIPE in case one of the output files is a pipe
>  * that doesn't consume all its input.  Good idea... */
>   signal(SIGPIPE, SIG_IGN);
>
>
> Sadly, this breaks POSIX SIGPIPE behaviour with respect to quitting when
> stdout (as a pipe) is closed.
>
> Despite the comment, GNU tee does not behave as the comment suggests.
>
> Comparing 1.27.2-2ubuntu3.2 with tee (GNU coreutils) 8.28
>
> I test with one output file and stdout that stops early causing SIGPIPE
>
> 1. GNU tee
>
> ( dd if=/dev/zero bs=1024 count=8192 ; echo done $? >&2  ) | ( tee
> /dev/null ; echo tee $? >&2) | dd bs=10 count=10 >/dev/null
>
> 10+0 records in
> 10+0 records out
> 100 bytes copied, 0.000387276 s, 258 kB/s
> tee 141
> done 141
>
> the first two pipeline stages have exit code 141 due to sigpipe as we
> would expect
>
> 2. busybox tee
>
> ( dd if=/dev/zero bs=1024 count=8192 ; echo done $? >&2  ) | ( busybox tee
> /dev/null ; echo tee $? >&2) | dd bs=10 count=10 >/dev/null
> 10+0 records in
> 10+0 records out
> 100 bytes copied, 0.000291134 s, 343 kB/s
> 8192+0 records in
> 8192+0 records out
> 8388608 bytes (8.4 MB, 8.0 MiB) copied, 0.0447136 s, 188 MB/s
> done 0
> tee 0
>
> both prior pipeline elements have exit code zero and the first stage
> processed all of the data
>
> The POSIX spec for tee reads:
> https://pubs.opengroup.org/onlinepubs/9699919799/utilities/tee.html
> CONSEQUENCES OF ERRORS
>
> If a write to any successfully opened *file* operand fails, writes to
> other successfully opened *file* operands and standard output shall
> continue, but the exit status shall be non-zero. Otherwise, the default
> actions specified in *Utility Description Defaults*
> <https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap01.html#tag_17_04>
>  apply.
>
> But this case deals with a failure to write to stdout, not a failure to
> write to a *file* operand.
>
> Certainly, with this behaviour, busybox tee does not comply with GNU tee
> as it appears to intend, so I suggest that the line signal(SIGPIPE,
> SIG_IGN) be removed.
>
> To meet the probable intent, the signal should probably be ignored while
> writing to file operands (in case they turn out to be pipes) and enabled
> each time when writing to stdout.
>
> Sam
>
If we get EPIPE on write to stdout, then fail like a decent tee.
We fail with SIGPIPE like GNU tee as emulating GNU tee seems to be the aim.

--- ./coreutils/tee.c.o	2019-09-13 07:50:47.134804213 +0100
+++ ./coreutils/tee.c	2019-09-13 09:09:40.280881938 +0100
@@ -70,7 +70,9 @@
 	}
 	retval = EXIT_SUCCESS;
 	/* gnu tee ignores SIGPIPE in case one of the output files is a pipe
-	 * that doesn't consume all its input.  Good idea... */
+	 * that doesn't consume all its input.  Good idea... 
+	 * An even better idea is to still respect SIGPIPE on stdout
+	 * which we do further on. */
 	signal(SIGPIPE, SIG_IGN);
 
 	/* Allocate an array of FILE *'s, with one extra for a sentinel. */
@@ -100,9 +102,12 @@
 #if ENABLE_FEATURE_TEE_USE_BLOCK_IO
 	while ((c = safe_read(STDIN_FILENO, buf, COMMON_BUFSIZE)) > 0) {
 		fp = files;
-		do
+		if (fwrite(buf, 1, c, *fp) != c && errno == EPIPE) {
+			kill_myself_with_s

Re: SIGPIPE and tee

2019-09-13 Thread Sam Liddicott
Here is a patch which invokes kill_myself_with_sig(SIGPIPE) if fwrite fails
with errno=EPIPE.

Quitting with a signal rather than a diagnostic output emulates GNU tee
which is in line with the apparent reason for busybox tee in ignoring
SIGPIPE in the first place.

I have tested it with and without CONFIG_FEATURE_TEE_USE_BLOCK_IO=y

As expected, dd succeeds for bs=1024 with CONFIG_FEATURE_TEE_USE_BLOCK_IO=y
but fails for without.
dd fails in both cases for bs=1024000
tee fails in both cases

( sleep 2 ; dd if=/dev/zero bs=1024000 count=5 ; echo dd $? > /dev/tty ; )
| {
build_output/sysroots-components/x86_64/busybox-native/bin/busybox.nosuid
tee /dev/null ; echo tee $? >/dev/tty ; } | sleep 1

( sleep 2 ; dd if=/dev/zero bs=1024 count=5 ; echo dd $? > /dev/tty ; ) | {
build_output/sysroots-components/x86_64/busybox-native/bin/busybox.nosuid
tee /dev/null ; echo tee $? >/dev/tty ; } | sleep 1

A colleague has suggested that *any* write failure to *stdout* by tee ought
to cause tee to quit, but I leave this to your consideration; something
like this *might* cover both cases but I haven't tested it:

if (fwrite(buf, 1, c, *fp) != c) {
  if (errno == EPIPE) kill_myself_with_sig(SIGPIPE);
  retval = EXIT_FAILURE;
  break;
}

Sam


On Thu, 12 Sep 2019 at 20:03, Sam Liddicott  wrote:

> In  https://git.busybox.net/busybox/tree/coreutils/tee.c we read:
>
>   /* gnu tee ignores SIGPIPE in case one of the output files is a pipe
>  * that doesn't consume all its input.  Good idea... */
>   signal(SIGPIPE, SIG_IGN);
>
>
> Sadly, this breaks POSIX SIGPIPE behaviour with respect to quitting when
> stdout (as a pipe) is closed.
>
> Despite the comment, GNU tee does not behave as the comment suggests.
>
> Comparing 1.27.2-2ubuntu3.2 with tee (GNU coreutils) 8.28
>
> I test with one output file and stdout that stops early causing SIGPIPE
>
> 1. GNU tee
>
> ( dd if=/dev/zero bs=1024 count=8192 ; echo done $? >&2  ) | ( tee
> /dev/null ; echo tee $? >&2) | dd bs=10 count=10 >/dev/null
>
> 10+0 records in
> 10+0 records out
> 100 bytes copied, 0.000387276 s, 258 kB/s
> tee 141
> done 141
>
> the first two pipeline stages have exit code 141 due to sigpipe as we
> would expect
>
> 2. busybox tee
>
> ( dd if=/dev/zero bs=1024 count=8192 ; echo done $? >&2  ) | ( busybox tee
> /dev/null ; echo tee $? >&2) | dd bs=10 count=10 >/dev/null
> 10+0 records in
> 10+0 records out
> 100 bytes copied, 0.000291134 s, 343 kB/s
> 8192+0 records in
> 8192+0 records out
> 8388608 bytes (8.4 MB, 8.0 MiB) copied, 0.0447136 s, 188 MB/s
> done 0
> tee 0
>
> both prior pipeline elements have exit code zero and the first stage
> processed all of the data
>
> The POSIX spec for tee reads:
> https://pubs.opengroup.org/onlinepubs/9699919799/utilities/tee.html
> CONSEQUENCES OF ERRORS
>
> If a write to any successfully opened *file* operand fails, writes to
> other successfully opened *file* operands and standard output shall
> continue, but the exit status shall be non-zero. Otherwise, the default
> actions specified in *Utility Description Defaults*
> <https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap01.html#tag_17_04>
>  apply.
>
> But this case deals with a failure to write to stdout, not a failure to
> write to a *file* operand.
>
> Certainly, with this behaviour, busybox tee does not comply with GNU tee
> as it appears to intend, so I suggest that the line signal(SIGPIPE,
> SIG_IGN) be removed.
>
> To meet the probable intent, the signal should probably be ignored while
> writing to file operands (in case they turn out to be pipes) and enabled
> each time when writing to stdout.
>
> Sam
>


0001-Add-SIGPIPE-handler-to-tee.patch
Description: Binary data
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: SIGPIPE and tee

2019-09-13 Thread Sam Liddicott
I also note that busybox tee treats a filename single hyphen as stdout,
contrary to POSIX.

I mention it only because it might save a few bytes to remove this special
case, and treat it as a regular file.

https://pubs.opengroup.org/onlinepubs/9699919799/utilities/tee.html
OPERANDS

The following operands shall be supported:
*file*A pathname of an output file. If a *file* operand is '-', it shall
refer to a file named *-*; implementations shall not treat it as meaning
standard output.


On Thu, 12 Sep 2019 at 20:03, Sam Liddicott  wrote:

> In  https://git.busybox.net/busybox/tree/coreutils/tee.c we read:
>
>   /* gnu tee ignores SIGPIPE in case one of the output files is a pipe
>  * that doesn't consume all its input.  Good idea... */
>   signal(SIGPIPE, SIG_IGN);
>
>
> Sadly, this breaks POSIX SIGPIPE behaviour with respect to quitting when
> stdout (as a pipe) is closed.
>
> Despite the comment, GNU tee does not behave as the comment suggests.
>
> Comparing 1.27.2-2ubuntu3.2 with tee (GNU coreutils) 8.28
>
> I test with one output file and stdout that stops early causing SIGPIPE
>
> 1. GNU tee
>
> ( dd if=/dev/zero bs=1024 count=8192 ; echo done $? >&2  ) | ( tee
> /dev/null ; echo tee $? >&2) | dd bs=10 count=10 >/dev/null
>
> 10+0 records in
> 10+0 records out
> 100 bytes copied, 0.000387276 s, 258 kB/s
> tee 141
> done 141
>
> the first two pipeline stages have exit code 141 due to sigpipe as we
> would expect
>
> 2. busybox tee
>
> ( dd if=/dev/zero bs=1024 count=8192 ; echo done $? >&2  ) | ( busybox tee
> /dev/null ; echo tee $? >&2) | dd bs=10 count=10 >/dev/null
> 10+0 records in
> 10+0 records out
> 100 bytes copied, 0.000291134 s, 343 kB/s
> 8192+0 records in
> 8192+0 records out
> 8388608 bytes (8.4 MB, 8.0 MiB) copied, 0.0447136 s, 188 MB/s
> done 0
> tee 0
>
> both prior pipeline elements have exit code zero and the first stage
> processed all of the data
>
> The POSIX spec for tee reads:
> https://pubs.opengroup.org/onlinepubs/9699919799/utilities/tee.html
> CONSEQUENCES OF ERRORS
>
> If a write to any successfully opened *file* operand fails, writes to
> other successfully opened *file* operands and standard output shall
> continue, but the exit status shall be non-zero. Otherwise, the default
> actions specified in *Utility Description Defaults*
> <https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap01.html#tag_17_04>
>  apply.
>
> But this case deals with a failure to write to stdout, not a failure to
> write to a *file* operand.
>
> Certainly, with this behaviour, busybox tee does not comply with GNU tee
> as it appears to intend, so I suggest that the line signal(SIGPIPE,
> SIG_IGN) be removed.
>
> To meet the probable intent, the signal should probably be ignored while
> writing to file operands (in case they turn out to be pipes) and enabled
> each time when writing to stdout.
>
> Sam
>
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


SIGPIPE and tee

2019-09-12 Thread Sam Liddicott
In  https://git.busybox.net/busybox/tree/coreutils/tee.c we read:

/* gnu tee ignores SIGPIPE in case one of the output files is a pipe
* that doesn't consume all its input.  Good idea... */
signal(SIGPIPE, SIG_IGN);


Sadly, this breaks POSIX SIGPIPE behaviour with respect to quitting when
stdout (as a pipe) is closed.

Despite the comment, GNU tee does not behave as the comment suggests.

Comparing 1.27.2-2ubuntu3.2 with tee (GNU coreutils) 8.28

I test with one output file and stdout that stops early causing SIGPIPE

1. GNU tee

( dd if=/dev/zero bs=1024 count=8192 ; echo done $? >&2  ) | ( tee
/dev/null ; echo tee $? >&2) | dd bs=10 count=10 >/dev/null

10+0 records in
10+0 records out
100 bytes copied, 0.000387276 s, 258 kB/s
tee 141
done 141

the first two pipeline stages have exit code 141 due to sigpipe as we would
expect

2. busybox tee

( dd if=/dev/zero bs=1024 count=8192 ; echo done $? >&2  ) | ( busybox tee
/dev/null ; echo tee $? >&2) | dd bs=10 count=10 >/dev/null
10+0 records in
10+0 records out
100 bytes copied, 0.000291134 s, 343 kB/s
8192+0 records in
8192+0 records out
8388608 bytes (8.4 MB, 8.0 MiB) copied, 0.0447136 s, 188 MB/s
done 0
tee 0

both prior pipeline elements have exit code zero and the first stage
processed all of the data

The POSIX spec for tee reads:
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/tee.html
CONSEQUENCES OF ERRORS

If a write to any successfully opened *file* operand fails, writes to other
successfully opened *file* operands and standard output shall continue, but
the exit status shall be non-zero. Otherwise, the default actions specified
in *Utility Description Defaults*
<https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap01.html#tag_17_04>
 apply.

But this case deals with a failure to write to stdout, not a failure to
write to a *file* operand.

Certainly, with this behaviour, busybox tee does not comply with GNU tee as
it appears to intend, so I suggest that the line signal(SIGPIPE, SIG_IGN)
be removed.

To meet the probable intent, the signal should probably be ignored while
writing to file operands (in case they turn out to be pipes) and enabled
each time when writing to stdout.

Sam
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox