Daniel Bump bump@match.stanford.edu writes:
Back to Problem 2 from my previous message.
Here's what is happening. Suppose I run:
perl twogtp-a --black "metamachine" --white "gnugo --mode gtp --quiet"
(There are two versions of twogtp in interface/gtp_examples, and twogtp-a is a little easier for me to parse.)
I can do this from perldb and as soon as pidb is open I can attach gdb to metamachine and/or gnugo. Metamachine stops at line 61:
if (!fgets(client_line, 128, stdin))
waiting for a command in stdin. This it should get when twogtp-a gets up to line 115 and prints "boardsize 19" but at this point deadlock occurs. Note that there is no deadlock if metamachine is run from the shell.
One difference is that stdin tends to be fully buffered unless it is a shell. I'd guess that the stdio library is being initialised before you drop in your replacements for fileid 0 and 1 (which is possibly a bad idea..?)
So when you run from the shell, stdin is set to be line-buffered, and then you drop a pipe into fd 0. But when it is spawned from twogtp, stdin is set fully buffered ? Ditto for stdout.
For this sort of application I would tend to use raw reads and writes, omitting the stdio library entirely.
Forcing (no more than) line buffering in stdio is probably essential.
I have an email from David referring to man IPC::Open2 on the dangers of open2. But I can't say I really understand why this deadlock occurs or how it can be avoided.
The problem is that when you do fprintf(), there is no guarantee that the data has actually been written out of the process buffers. So process A thinks it has sent the command and is blocked waiting for the reply. But the message is still in A's stdio buffers, and so process is still blocked waiting to read it. => deadlock.
dd
David wrote:
I have an email from David referring to man IPC::Open2 on the dangers of open2. But I can't say I really understand why this deadlock occurs or how it can be avoided.
The problem is that when you do fprintf(), there is no guarantee that the data has actually been written out of the process buffers. So process A thinks it has sent the command and is blocked waiting for the reply. But the message is still in A's stdio buffers, and so process is still blocked waiting to read it. => deadlock.
But in this case the printf is done by the perl twogtp command:
print $black_in "boardsize $size\n";
Here $black_in is the file descriptor created with:
$pidb = open2($black_out, $black_in, $black);
and man IPC::Open2 says:
The write filehandle will have autoflush turned on.
Doesn't this mean that the data should have been written out of the buffer?
Dan