Wandering Thoughts archives

2007-10-02

A gotcha with 'bidirectional' pipes to commands

By bidirectional pipes I mean a situation where you start a subordinate program and both write to its standard input and read from its standard output. There are a fair number of programs that are programmed like the following pseudo-code:

to, from = pipecmd("subprogram", "rw")
write(to, stuff)
reply = read(from)

People write these programs, test them a bit, start using them, have them work, and then one day wake up to discover that their program has locked up; it and the subprogram are both running, doing nothing. (A system call tracer will tell them that both programs are blocked in write().)

It's not really surprising that people write pipes like this; this code is simple, obvious, and works most of the time. Specifically, it works as long as the subprogram reads almost all of its input before producing enough output to fill up its standard output pipe. After that the subprogram blocks trying to write output, because no one is reading it, and the main program blocks trying to write input to the subprogram, because the subprogram is blocked writing output.

(Often this means that the program works in testing and early in its production use, when it is only being asked to deal with relatively small amounts of data, and it is only when things grow that it blows up.)

Unfortunately there is no good simple way out of this. The best but most complicated approach is to make your program use a select() or poll() based loop to simultaneously write to the subprogram and read its output. The brute force way is to use either fork() or threads to let you do the write() and the read() at the same time.

unix/PipeReadWriteIssue written at 20:54:26;


Page tools: See As Normal.
Search:
Login: Password:

This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.