Bug 7436

Summary: unreliable pipe handling
Product: Busybox Reporter: Michael Tokarev <mjt+busybox>
Component: OtherAssignee: unassigned
Status: RESOLVED INVALID    
Severity: normal CC: busybox-cvs
Priority: P5    
Version: unspecified   
Target Milestone: ---   
Hardware: PC   
OS: Linux   
Host: Target:
Build:

Description Michael Tokarev 2014-09-14 07:20:57 UTC
As has been submitted to debian BTS, http://bugs.debian.org/761423#10 -- sometimes, pipe between two components of bysybox (in this case it is find and dd) does not work in a reliable way.  Quoting the testcase here.

----
    % busybox sh
    
    BusyBox v1.22.1 (Debian 1:1.22.0-8) built-in shell (ash)
    Enter 'help' for a list of built-in commands.
    
    ~ $ mkdir /tmp/emptytest
    ~ $ touch /tmp/emptytest/.x
    ~ $ find /tmp/emptytest/ -name "*?" | dd count=1 2>/dev/null
    /tmp/emptytest/
    ~ $ find /tmp/emptytest/ -name "*?" | dd count=1 2>/dev/null 
    /tmp/emptytest/
    ~ $ find /tmp/emptytest/ -name "*?" | dd count=1 2>/dev/null 
    /tmp/emptytest/
    /tmp/emptytest/.x
    ~ $ find /tmp/emptytest/ -name "*?" | dd count=1 2>/dev/null 
    /tmp/emptytest/
    ~ $ find /tmp/emptytest/ -name "*?" | dd count=1 2>/dev/null 
    /tmp/emptytest/
    /tmp/emptytest/.x
    ~ $ find /tmp/emptytest/ -name "*?" | dd count=1 2>/dev/null 
    /tmp/emptytest/
    ~ $ find /tmp/emptytest/ -name "*?" | dd count=1 2>/dev/null 
    /tmp/emptytest/
    /tmp/emptytest/.x
    
The output should be always:

    /tmp/emptytest/
    /tmp/emptytest/.x
----

I can confirm this result on my box too.
Comment 1 Denys Vlasenko 2014-09-15 23:23:51 UTC
(In reply to comment #0)
> As has been submitted to debian BTS, http://bugs.debian.org/761423#10 --
> sometimes, pipe between two components of bysybox (in this case it is find and
> dd) does not work in a reliable way.  Quoting the testcase here.
> 
> ----
>     % busybox sh
> 
>     BusyBox v1.22.1 (Debian 1:1.22.0-8) built-in shell (ash)
>     Enter 'help' for a list of built-in commands.
> 
>     ~ $ mkdir /tmp/emptytest
>     ~ $ touch /tmp/emptytest/.x
>     ~ $ find /tmp/emptytest/ -name "*?" | dd count=1 2>/dev/null
>     /tmp/emptytest/
>     ~ $ find /tmp/emptytest/ -name "*?" | dd count=1 2>/dev/null 
>     /tmp/emptytest/
>     ~ $ find /tmp/emptytest/ -name "*?" | dd count=1 2>/dev/null 
>     /tmp/emptytest/
>     /tmp/emptytest/.x
>     ~ $ find /tmp/emptytest/ -name "*?" | dd count=1 2>/dev/null 
>     /tmp/emptytest/
>     ~ $ find /tmp/emptytest/ -name "*?" | dd count=1 2>/dev/null 
>     /tmp/emptytest/
>     /tmp/emptytest/.x
>     ~ $ find /tmp/emptytest/ -name "*?" | dd count=1 2>/dev/null 
>     /tmp/emptytest/
>     ~ $ find /tmp/emptytest/ -name "*?" | dd count=1 2>/dev/null 
>     /tmp/emptytest/
>     /tmp/emptytest/.x
> 
> The output should be always:
> 
>     /tmp/emptytest/
>     /tmp/emptytest/.x

I think you are mistaken.

{ echo a; echo b; } | dd count=1 2>/dev/null

usually (almost always) prints two lines: "a", "b". But

{ echo a; sleep 1; echo b; } | dd count=1 2>/dev/null

always prints only one line, "a". Because dd is instructed to do only one read (count=1), and if only "a\n" is ready to be read, then dd gets that, outputs it, and exits.



No, it should not be always this.