os.fork() different in cgi-script?

  • Thread starter Andreas Kuntzagk
  • Start date
A

Andreas Kuntzagk

Hi,

following code:

#!/usr/bin/python

import os
import sys

def main():
print "Content-Type: text/plain\n\n"
print os.getpid()

childPID = os.fork()
if childPID == 0:
sys.exit()
else:
os.wait()

if __name__ == "__main__":
main()

when run on a shell, gives the result:
---------------------------
Content-Type: text/plain


20953
----------------------------

but run as a cgi-script it gives:
---------------------------
21039
Content-Type: text/plain


21039
---------------------------
So it looks the main() is run 2 times.
Is it so? And if yes, why?

I googled for this but only found a similar question from 1997 and no
answer.

Ciao, Andreas
 
A

Andreas Kuntzagk

Sorry, forgot:

this is Python 2.2.1, apache 1.3.26 on SuSE 8.1

Andreas
 
M

Michael Coleman

Andreas Kuntzagk said:
def main():
print "Content-Type: text/plain\n\n"
print os.getpid()

childPID = os.fork()
if childPID == 0:
sys.exit()
else:
os.wait()

if __name__ == "__main__":
main()

when run on a shell, gives the result:
---------------------------
Content-Type: text/plain


20953
----------------------------

but run as a cgi-script it gives:
---------------------------
21039
Content-Type: text/plain


21039

Probably because stdout is being buffered here. The pid got written in the buffer (but not yet actually printed), then the process was forked, then the buffer got flushed (written out) by each child.

One solution would be to make sure everything is flushed before you fork.

Mike
 
A

Andreas Kuntzagk

Probably because stdout is being buffered here. The pid got written in
the buffer (but not yet actually printed), then the process was forked,
then the buffer got flushed (written out) by each child.

One solution would be to make sure everything is flushed before you
fork.

Thanx, that's it. Is it possible/advisable to make stdout unbuffered?

Andreas
 
J

Juha Autero

Andreas Kuntzagk said:
So it looks the main() is run 2 times.
Is it so? And if yes, why?

No, it isn't. The problem is that Python uses C STDIO library that has
buffered input and output. The text written in stdout is written in
buffer. Since child process created by fork() is almost identical to
parent process, it will also have a copy of stdout buffer. When
process exits, it closes stdout, which flushes the buffer. So, both
buffers are written to stdout and that causes everything to be printed
twice.

The reason why this doesn happen on command line is that buffers to
terminals are flushed after newline. You can see that by redirecting
script output to file:

$ python script.py >output
$ cat output
Content-Type: text/plain


4309
Content-Type: text/plain


4309
I googled for this but only found a similar question from 1997 and no
answer.

Which is strange since this common problem and has nothing to do with
Python.
 
E

Erwin S. Andreasen

Andreas Kuntzagk said:
following code:
print "Content-Type: text/plain\n\n"
print os.getpid()

childPID = os.fork()
if childPID == 0:
sys.exit()
else:
os.wait()
[...]

So it looks the main() is run 2 times.
Is it so? And if yes, why?

The problem is buffering. When you run your script from the command
line, the standard output is a terminal and becomes line-buffered.
Thus at the time you fork, the stdout buffer has been flushed.

When you run it as a CGI script, stdout is a socket and thus not a
terminal -- so it becomes block buffered. At the time you fork, each
copy of stdout holds all of our unflushed output. When the two
processes exit they will both flush the output, resulting in it being
printed twice.

You can use sys.stdout.flush() to flush the pending output before
forking.
 
A

Andreas Kuntzagk

Which is strange since this common problem and has nothing to do with
Python.

Not so strange, because assuming a Python feature I also included "python"
in the googlequest(tm).

Andreas
 
M

Michael Coleman

Andreas Kuntzagk said:
Thanx, that's it. Is it possible/advisable to make stdout unbuffered?

Probably. I'd be more inclined to just do an explicit flush in the
few places where they are specifically needed, though.

Mike
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top