<div dir="ltr">Here is a patch which invokes kill_myself_with_sig(SIGPIPE) if fwrite fails with errno=EPIPE.<div><br></div><div>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.</div><div></div><div><br></div><div>I have tested it with and without CONFIG_FEATURE_TEE_USE_BLOCK_IO=y</div><div><br></div><div>As expected, dd succeeds for bs=1024 with CONFIG_FEATURE_TEE_USE_BLOCK_IO=y but fails for without.</div><div>dd fails in both cases for bs=1024000</div><div>tee fails in both cases</div><div><br></div><div><div>( 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<br></div><div><br></div><div>( 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<br></div><div></div></div><div><br></div><div>A colleague has suggested that <b>any</b> write failure to <b>stdout</b> by tee ought to cause tee to quit, but I leave this to your consideration; something like this <b>might</b> cover both cases but I haven't tested it:</div><div><br></div><div>if (fwrite(buf, 1, c, *fp) != c) {</div><div>  if (errno == EPIPE) kill_myself_with_sig(SIGPIPE);</div><div>  retval = EXIT_FAILURE;</div><div>  break;<br>}<br></div><div><br></div><div>Sam</div><div><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, 12 Sep 2019 at 20:03, Sam Liddicott <<a href="mailto:sam@liddicott.com">sam@liddicott.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">In 

<a href="https://git.busybox.net/busybox/tree/coreutils/tee.c" target="_blank">https://git.busybox.net/busybox/tree/coreutils/tee.c</a> we read:<div><pre style="padding:0px;margin-top:0px;margin-bottom:0px;color:rgb(0,0,0);font-size:13.3333px">     <span class="gmail-m_5126291428043663572gmail-cm" style="color:rgb(136,136,136)">/* gnu tee ignores SIGPIPE in case one of the output files is a pipe</span>
<span class="gmail-m_5126291428043663572gmail-cm" style="color:rgb(136,136,136)">      * that doesn't consume all its input.  Good idea... */</span>
        <span class="gmail-m_5126291428043663572gmail-n">signal</span><span class="gmail-m_5126291428043663572gmail-p">(</span><span class="gmail-m_5126291428043663572gmail-n">SIGPIPE</span><span class="gmail-m_5126291428043663572gmail-p">,</span> <span class="gmail-m_5126291428043663572gmail-n">SIG_IGN</span><span class="gmail-m_5126291428043663572gmail-p">);</span></pre></div><div><br></div><div>Sadly, this breaks POSIX SIGPIPE behaviour with respect to quitting when stdout (as a pipe) is closed.</div><div><br></div><div>Despite the comment, GNU tee does not behave as the comment suggests.</div><div><br></div><div>Comparing 1.27.2-2ubuntu3.2 with tee (GNU coreutils) 8.28</div><div><br></div><div>I test with one output file and stdout that stops early causing SIGPIPE</div><div><br></div><div>1. GNU tee</div><div><br></div><div>( dd if=/dev/zero bs=1024 count=8192 ; echo done $? >&2  ) | ( tee /dev/null ; echo tee $? >&2) | dd bs=10 count=10 >/dev/null<br></div><div><br></div><div>10+0 records in<br>10+0 records out<br>100 bytes copied, 0.000387276 s, 258 kB/s<br>tee 141<br>done 141<br></div><div><br></div><div>the first two pipeline stages have exit code 141 due to sigpipe as we would expect</div><div><br></div><div>2. busybox tee</div><div><br></div><div>( 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<br>10+0 records in<br>10+0 records out<br>100 bytes copied, 0.000291134 s, 343 kB/s<br>8192+0 records in<br>8192+0 records out<br>8388608 bytes (8.4 MB, 8.0 MiB) copied, 0.0447136 s, 188 MB/s<br>done 0<br>tee 0<br></div><div><br></div><div>both prior pipeline elements have exit code zero and the first stage processed all of the data</div><div><br></div><div>The POSIX spec for tee reads:</div><div><a href="https://pubs.opengroup.org/onlinepubs/9699919799/utilities/tee.html" target="_blank">https://pubs.opengroup.org/onlinepubs/9699919799/utilities/tee.html</a>  <br><h4 class="gmail-m_5126291428043663572gmail-mansect" style="color:rgb(0,102,0);font-style:italic;font-size:12pt">CONSEQUENCES OF ERRORS</h4><blockquote style="color:rgb(0,0,0);font-family:Verdana,Arial,Helvetica,sans-serif;font-size:13.3333px"><p>If a write to any successfully opened <i>file</i> operand fails, writes to other successfully opened <i>file</i> operands and standard output shall continue, but the exit status shall be non-zero. Otherwise, the default actions specified in <a href="https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap01.html#tag_17_04" style="color:rgb(102,102,255)" target="_blank"><i>Utility Description Defaults</i></a> apply.</p></blockquote>But this case deals with a failure to write to stdout, not a failure to write to a <i>file</i> operand.</div><div><br></div><div>Certainly, with this behaviour, busybox tee does not comply with GNU tee as it appears to intend, so I suggest that the line <span class="gmail-m_5126291428043663572gmail-n">signal</span><span class="gmail-m_5126291428043663572gmail-p">(</span><span class="gmail-m_5126291428043663572gmail-n">SIGPIPE</span><span class="gmail-m_5126291428043663572gmail-p">,</span> <span class="gmail-m_5126291428043663572gmail-n">SIG_IGN</span><span class="gmail-m_5126291428043663572gmail-p">) be removed.</span></div><div><span class="gmail-m_5126291428043663572gmail-p"><br></span></div><div><span class="gmail-m_5126291428043663572gmail-p">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.</span></div><div><br></div><div>Sam </div></div>
</blockquote></div>