From: Prof Craver on
Hi,

I am using a bidirectional pipe to filter data through a Unix command,
but for some commands it hangs forever. I suspect that the command is
waiting for an EOF on the input side before sending output, and I
can't figure how to force this.

Thankfully the command I need to invoke knows when to respond, but I
can't help but wonder how you can successfully pass data through the
sort command with a bidirectional pipe.

My code is as follows:

proc bipipe {command input} {
set pipe [open "|$command" r+]
fconfigure $pipe -blocking 0
fileevent $pipe readable [list bipipedone $pipe]

if {[info exists ::bipipeout]} {unset ::bipipeout}
puts -nonewline $pipe $input; flush $pipe
vwait ::bipipeout

close $pipe
set ::bipipeout
}
proc bipipedone chan {
fileevent $chan readable {}
set ::bipipeout [read $chan]
}

puts [bipipe cat "Dave
Carol
Alice
Bob"] ;# This works just fine

puts [bipipe sort "Dave
Carol
Alice
Bob"] ;# This vwaits indefinitely
From: Glenn Jackman on
At 2010-03-10 01:15PM, "Prof Craver" wrote:
> Hi,
>
> I am using a bidirectional pipe to filter data through a Unix command,
> but for some commands it hangs forever. I suspect that the command is
> waiting for an EOF on the input side before sending output, and I
> can't figure how to force this.
>
> Thankfully the command I need to invoke knows when to respond, but I
> can't help but wonder how you can successfully pass data through the
> sort command with a bidirectional pipe.
[...]
> if {[info exists ::bipipeout]} {unset ::bipipeout}

Side note: depending on your version, use: unset -nocomplain ::bipipeout

[...]

> puts [bipipe cat "Dave
> Carol
> Alice
> Bob"] ;# This works just fine
>
> puts [bipipe sort "Dave
> Carol
> Alice
> Bob"] ;# This vwaits indefinitely

Yes, sort has to wait for stdin to close before it can be sure it has
all the data to sort.

You want to use the "<<" option to [exec]

set data "Dave\nCarol\nAlice\nBob\n"
puts [exec sort << $data]


--
Glenn Jackman
Write a wise saying and your name will live forever. -- Anonymous
From: Prof Craver on
> You want to use the "<<" option to [exec]
>
>     set data "Dave\nCarol\nAlice\nBob\n"
>     puts [exec sort << $data]

Thank you; I had a feeling I was doing it the hard way.

--X
From: Alexandre Ferrieux on
On Mar 10, 7:15 pm, Prof Craver <xcottcra...(a)gmail.com> wrote:
> Hi,
>
> I am using a bidirectional pipe to filter data through a Unix command,
> but for some commands it hangs forever.  I suspect that the command is
> waiting for an EOF on the input side before sending output, and I
> can't figure how to force this.
>
> Thankfully the command I need to invoke knows when to respond, but I
> can't help but wonder how you can successfully pass data through the
> sort command with a bidirectional pipe.

This case was the motivation for TIP #332 (half-close), implemented on
the 8.6 branch in Dec 2008:

set f [open |sort r+]
puts $f $somedata
close $f write
set sorted [read $f]
close $f read

If you need to do this before 8.6 though, the usual trick is to have
some in-band EOF marker, with a dedicated filter process in front:

set f [open {|sed -n -e {/^MYEOF$/ q} -e p | sort} r+]
puts $f $somedata
puts $f MYEOF
flush $f
set sorted [read $f]
close $f

-Alex