12-22-05 10:57 PM
>Here's a named pipes issue that just came up.
>
>Let's say you have 2 processes A and B,
>with two named pipes between them, the A->B pipe
>and a return pipe B->A.
Think deadlock. Any time you have two pipes (named or unnamed) in
opposite directions between processes, you need to deal with the
problem somehow.
>If I write from process A to the A->B pipe,
>let's say 1000 bytes, but a bug in the reader
>process B causes it to read only 999 bytes,
>I can potentially end up with a deadlock situation:
You can get the same deadlock if process A writes the data to the
pipe via stdio, but fails to fflush() the data. If B sits there
waiting for more data before sending anything more to A, you have
deadlock. You can also have a deadlock if A is feeding data to B,
B is returning some to A and fills up the pipe, and A won't take
any data back from B until it delivers it all. In the first case
you have both processes blocking on reads. In the second case you
have both processes blocking on writes.
I wouldn't advise trying to work around deadlocks caused
if the program has a bug: REMOVE THE BUG.
One (poor) solution to this if process A is something you do not
have source code to A, so you can't insert fflush() calls or setvbuf,
is to have B call suck() on the pipe. The problem with this is
that to my knowledge, NO ONE has implemented suck().
Threatening the child with signals rarely works.
>namely, process A remains blocked after writing
>until the pipe is empty (it seems) and process B, if it
>thinks it has emptied the pipe may very well
>try to send data back on the return pipe,
>but will block after writing as well until A
>has emptied the pipe, but that will never
>happen because A is blocked.
>I know, you can set nonblocking mode
>but if either A or B is coded in something
>other than the C Language, there is a chance that that
>mode won't even be available.
General approaches to the two-way data problem:
(1) Use a protocol that requires you to deliver *ALL* of your data
to the child process before reading *ANY* of it (e.g. sort programs).
This is likely to require modification to the child.
(2) Use non-blocking I/O or select() or poll() to avoid having writing
or reading block each other. This can work without modification of
the child.
(3) Place fflush() calls at appropriate places in the parent and
child (like just before doing a blocking read), or stick to write() calls.
This is likely to require modification to the child.
Gordon L. Burditt
[ Post a follow-up to this message ]
|