パイプのデッドロック

親プロセスが子プロセスの標準出力を読み出している一方で、子プロセスが大量のデータを標準エラー出力に書き込んでいる場合、この子プロセスから出力を読み出そうとするとデッドロックが発生します。

http://www.python.jp/doc/2.4/lib/popen2-flow-control.html

こういうこと?

a.py

import subprocess

try:
    p = subprocess.Popen("python b.py", shell=True, bufsize=0,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE)
except OSError:
    print "popen failed"
    sys.exit(1)

print "from child [%s]" % p.stdout.readline() 

b.py

import sys

log = open("log2.txt", "w")

for i in xrange(1000000):
    if i % 1000 == 0:
        print >>log, "i = %i" % i
    print >>sys.stderr, "print to stderr"

print "print to stdout"


C版

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
	int stdout_pipe[2];
	int stderr_pipe[2];
	int pid;
	char buf[256];

	printf("_PC_PIPE_BUF = %d\n", _PC_PIPE_BUF);

	pipe(stdout_pipe);
	pipe(stderr_pipe);

	pid = fork();

	if (pid < 0) {
		perror("fork");
		exit(1);
	}
	else if (pid == 0) {
		const char* str = "print to stderr\n";
		int i;
		FILE* log = fopen("log.txt", "w");
		// child
		close(stdout_pipe[0]);
		close(stderr_pipe[0]);
		dup2(stdout_pipe[1], 1);
		dup2(stderr_pipe[1], 2);
		for (i=0; i<10000; i++) {
			fprintf(stderr, str);
			if (i % 1000 == 0) {
				fprintf(log, "i = %d\n", i);
				fflush(log);
			}
		}
		fprintf(log, "Finish\n");
		fclose(log);
		printf("print to stdout\n");
	}
	else {
		close(stdout_pipe[1]);
		close(stderr_pipe[1]);
		memset((void*)buf, 0, sizeof(buf));
		read(stdout_pipe[0], buf, sizeof(buf) - 1);
		printf("from child [%s]\n", buf);
	}

	return 0;
}