UNIX commands in C

shap shap at shasta.Stanford.EDU
Tue Apr 30 02:28:50 AEST 1991


In article <GLENN.91Apr29104336 at curie.ces.cwru.edu> glenn at curie.ces.cwru.edu (Glenn Crocker) writes:
>
>Check out the popen() function.  It allows you to open a pipe to a
>specified program and then read from it or write to it just like a
>normal file descriptor (FILE *).  If you'd like an example program
>that uses it, mail me.

popen(3) also has an interesting "feature."  It is essentially useless
unless the program you run from it doesn't read from stdin.  Here's
why.

A typical filter works, logically, on the model

	read all input
	process (churn churn)
	write all output

A real UNIX filter, on the other hand, frequently operates on the
model

	read some input
	process it
	write result
	read some more input
	process it
	...

So here's what can happen if you aren't careful:

	1. Parent program does a popen(3), and happily starts writing
	   to the pipe, assuming that it should dump the whole of the
	   input into the child program.

	2. Child program (the filter) processes some input and writes 
	   results to it's output (which the parent will eventually
	   read).

	3. Pipe buffer on the child output fills, because the parent
	   hasn't done any reads of the results yet.

	4. Child blocks, trying to write output to the pipe.

	5. Pipe buffer on the child input fills, because the child is
	   no longer reading it.

	6. Parent blocks.

Et Voilla! instant deadlock.  For those of you who don't believe this
happens, talk to some people who have had to port various window
managers.

Now here's the bad news.  To work around this limitation, you either
have to

	1. Know the pipe buffer size and operate accordingly
	2. Use asynchronous IO and buffer up the return stuff yourself

both of which are machine dependent (buf size clearly, not all
machines have asynch I/O).

The portable solution is to check how many bytes are writeable to the
pipe at any given time and if there aren't enough switch to buffering
up the input for a while to allow the child to run.  Needless to say,
this solution is UGLY.

Expert quiz question for the week: write a version of popen(3) that
doesn't have this feature.

[This problem was first brought to my attention by Mike Bianchi.  I
think he may have been the author of popen(3).]


Jonathan Shapiro



More information about the Comp.lang.c mailing list