#59 unbuffer -p should have an option to wait

open
nobody
None
5
2008-12-16
2008-12-16
Morty
No

As is documented in the manpage, "$command1 | unbuffer -p $command2" stops processing $command2 as soon as command1 exits. Contrived example:

uname | unbuffer -p sh -c "sleep 1; cat"

The workaround in the manpage amounts to:

(uname; sleep 2) | unbuffer -p sh -c "sleep 1; cat"

However, the above is clunky, and not really reliable: what if the system is unusually busy one day so $command2 takes longer to run than even the modified $command1? Meanwhile, it's a common case for $command2 to be well-behaved -- i.e. grep, or the like. So it would be nice if there were an option that, when $command1 exits, unbuffer feeds an EOF to $command2 and then waits for it.

Discussion

  • Andy Goth
    Andy Goth
    2008-12-16

    Tcl does not support closing a child process's stdin without also closing its stdout/stderr and killing it. In order to "feed an EOF" to the child process and wait for it to complete, such a shutdown()-like feature is necessary.

     
  • This was true until now :-)
    TIP332 has been accepted, giving you a half-close [close $ch w|r]
    Just wait for 8.6b1 ;-)

    However I fail to see what this has to do with the current bug, which is in an external C program.
    This C program has all freedom to handle separately the in and out ptys, and to close only the in-pty when EOF is met.
    So it has no excuse...

     
  • Morty
    Morty
    2008-12-18

    How is unbuffer an external C program? It looks to me like an expect script.

     
  • Morty
    Morty
    2008-12-20

    The "unbuffer" that is installed by default as part of the actual expect source distribution is a script. This is the unbuffer to which this bug refers. This is also the unbuffer that bug 2434894 refers to. In particular:

    $ cat $(which unbuffer)
    #!/bin/sh
    # \ exec expect -- "$0" ${1+"$@"}
    # Description: unbuffer stdout of a program
    # Author: Don Libes, NIST

    if {[string compare [lindex $argv 0] "-p"] == 0} {
    # pipeline
    set stty_init "-echo"
    eval spawn -noecho [lrange $argv 1 end]
    interact
    } else {
    set stty_init "-opost"
    eval spawn -noecho $argv
    set timeout -1
    expect
    }