os.fork() different in cgi-script?

Discussion in 'Python' started by Andreas Kuntzagk, Jul 2, 2003.

  1. 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
     
    Andreas Kuntzagk, Jul 2, 2003
    #1
    1. Advertising

  2. Sorry, forgot:

    this is Python 2.2.1, apache 1.3.26 on SuSE 8.1

    Andreas
     
    Andreas Kuntzagk, Jul 2, 2003
    #2
    1. Advertising

  3. "Andreas Kuntzagk" <> writes:
    > 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?


    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

    --
    Mike Coleman, Scientific Programmer, +1 816 926 4419
    Stowers Institute for Biomedical Research
    1000 E. 50th St., Kansas City, MO 64110
     
    Michael Coleman, Jul 2, 2003
    #3
  4. On Wed, 02 Jul 2003 09:50:03 +0000, Michael Coleman wrote:

    > 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
     
    Andreas Kuntzagk, Jul 2, 2003
    #4
  5. Andreas Kuntzagk

    Juha Autero Guest

    "Andreas Kuntzagk" <> writes:

    > 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.
    --
    Juha Autero
    http://www.iki.fi/jautero/
    Eschew obscurity!
     
    Juha Autero, Jul 2, 2003
    #5
  6. "Andreas Kuntzagk" <> writes:

    > 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.

    --
    ===============================================================
    <> Herlev, Denmark
    <URL:http://www.andreasen.org/> <*>
    ===============================================================
     
    Erwin S. Andreasen, Jul 2, 2003
    #6

  7. >> 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.


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

    Andreas
     
    Andreas Kuntzagk, Jul 2, 2003
    #7
  8. "Andreas Kuntzagk" <> writes:
    > 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

    --
    Mike Coleman, Scientific Programmer, +1 816 926 4419
    Stowers Institute for Biomedical Research
    1000 E. 50th St., Kansas City, MO 64110
     
    Michael Coleman, Jul 2, 2003
    #8
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Shailan
    Replies:
    2
    Views:
    1,033
    Shailan
    Dec 15, 2003
  2. praba kar

    Python-cgi or Perl-cgi script doubt

    praba kar, Jul 30, 2005, in forum: Python
    Replies:
    1
    Views:
    648
    Michael Sparks
    Jul 30, 2005
  3. Eric Snow

    os.fork and pty.fork

    Eric Snow, Jan 8, 2009, in forum: Python
    Replies:
    0
    Views:
    575
    Eric Snow
    Jan 8, 2009
  4. Kushal Kumaran
    Replies:
    0
    Views:
    423
    Kushal Kumaran
    Jan 10, 2011
  5. kath
    Replies:
    4
    Views:
    654
    J. Gleixner
    Apr 9, 2007
Loading...

Share This Page