S
S McAfee
Consider this fairly basic pipe/fork program:
--------------------
import os, sys, time
r, w = os.pipe()
pid = os.fork()
if pid == 0:
os.dup2(w, sys.stdout.fileno())
os.close(w)
os.close(r)
sys.stdout.write("This should appear right away!\n")
sys.stdout.close()
time.sleep(3)
sys.exit(0)
os.close(w)
r = os.fdopen(r, "r")
str = r.readline()
print 'Got line "%s"\n' % str
os.wait()
--------------------
The child process dups the write end of the pipe to stdout, closes both
ends of the pipe, writes a line to stdout, closes stdout, and waits a
few seconds before exiting. Meanwhile, the parent closes the write end of
the pipe, reads a line from the read end, prints it, and waits for the
child to exit.
What I *expected* to happen was that the parent would immediately report
the line printed by the child, since the child's stdout stream should be
flushed when it is closed. Instead, the parent waits three seconds before
printing the line! I can't figure out where the data is getting hung up.
When I write the equivalent program in C or Perl, I get the text from the
child right away.
Strangely, if I skip the dup-to-stdout step and write directly to the pipe,
like this:
if pid == 0:
os.close(r)
w = os.fdopen(w, "w")
w.write("This should appear right away!\n")
w.close()
time.sleep(3)
exit(0)
....then the text does indeed appear right away. Bizarrely, if I print any
text at all to stdout before forking:
r, w = os.pipe()
print "*",
sys.stdout.flush()
pid = os.fork()
....then that ALSO makes the child-generated text appear in the parent
immediately! WTF?
I am seriously bamboozled here. Can anyone explain to me what the hell is
happening? Thanks in advance.
....OK, just before I was about to post this article, I discovered that if I
change sys.stdout.close() to sys.stdout.flush() in my original program, I
get the expected behavior! Gah! Am I to understand that in Python,
closing a file does not flush the file?
--------------------
import os, sys, time
r, w = os.pipe()
pid = os.fork()
if pid == 0:
os.dup2(w, sys.stdout.fileno())
os.close(w)
os.close(r)
sys.stdout.write("This should appear right away!\n")
sys.stdout.close()
time.sleep(3)
sys.exit(0)
os.close(w)
r = os.fdopen(r, "r")
str = r.readline()
print 'Got line "%s"\n' % str
os.wait()
--------------------
The child process dups the write end of the pipe to stdout, closes both
ends of the pipe, writes a line to stdout, closes stdout, and waits a
few seconds before exiting. Meanwhile, the parent closes the write end of
the pipe, reads a line from the read end, prints it, and waits for the
child to exit.
What I *expected* to happen was that the parent would immediately report
the line printed by the child, since the child's stdout stream should be
flushed when it is closed. Instead, the parent waits three seconds before
printing the line! I can't figure out where the data is getting hung up.
When I write the equivalent program in C or Perl, I get the text from the
child right away.
Strangely, if I skip the dup-to-stdout step and write directly to the pipe,
like this:
if pid == 0:
os.close(r)
w = os.fdopen(w, "w")
w.write("This should appear right away!\n")
w.close()
time.sleep(3)
exit(0)
....then the text does indeed appear right away. Bizarrely, if I print any
text at all to stdout before forking:
r, w = os.pipe()
print "*",
sys.stdout.flush()
pid = os.fork()
....then that ALSO makes the child-generated text appear in the parent
immediately! WTF?
I am seriously bamboozled here. Can anyone explain to me what the hell is
happening? Thanks in advance.
....OK, just before I was about to post this article, I discovered that if I
change sys.stdout.close() to sys.stdout.flush() in my original program, I
get the expected behavior! Gah! Am I to understand that in Python,
closing a file does not flush the file?