Apache and os.fork() in CGI-Binaries

Matt Harden matth at ninenet.com
Thu Mar 8 22:20:19 EST 2001


Simon,

You need os.dup2().  Like this:
   logfile = os.open("/path/to/logfile",os.O_CREAT|os.O_WRONLY)
   os.lseek(logfile, 0, 2)  /* seek to end */
   os.dup2(logfile, sys.stdout.fileno())
   os.dup2(logfile, sys.stderr.fileno())
   os.close(logfile)

I would also close stdin like this:
   devnull = os.open("/dev/null", os.O_RDONLY)
   os.dup2(devnull, sys.stdin.fileno())
   os.close(devnull)

If you do that, you don't need the close() calls anymore.  Also make
sure you call sys.stdout.flush() and sys.stderr.flush() before you
os.fork().  Otherwise you could get duplicate output in some situations.

Hope this helps!
Matt

Simon Budig wrote:
> 
> Hi all.
> 
> I am currently developing a CGI-Binary which starts a second
> (long running) process. The problem is: Apache keeps the
> connection open until the fork()'ed child exits.
> 
> Discussing this thing with friends we came to the conclusion
> that some open filedescriptors keep the connection between the forked
> child and the apache alive:
> 
> 1) Apache gets a request
> 2) Apache starts CGI-Script (Python). This is the parent process
> 3) Parent process forks and creates the child
> 4) Parent process exits
> 5) Child process exits
> 6) Apache closes the connection to the browser.
> 
> But I need the closed connection after step 4. Since the Child
> inherits all filedescriptors, this is probably the thing that
> tells apache to keep the connection open.
> 
> I tried various things:
> 
> sys.stdout.close()
> sys.stdin.close()
> sys.stderr.close()
> 
> then I added
> 
> sys.__stdout__.close()
> sys.__stdin__.close()
> sys.__stderr__.close()
> 
> and this did not help. Finally i tried:
> 
> os.close (sys.stdout.fileno ())
> os.close (sys.stdin.fileno())
> os.close (sys.stderr.fileno ())
> 
> But at that time the Child does not run properly to the end.
> Of course I do something a la
> 
> logfile = open (mebong.basedir + "/logfile", "a")
> sys.stdout = sys.stderr = logfile
> 
> immediately afterwards, but this does not help.
> 
> So - how can I release all filedescriptors inherited from the parent?
> 
> The relevant parts from my code are:
> 
> -------------------------------
> # this is from the CGI-Binary
> childpid = os.fork ()
> if not childpid:
>    os.execv ("/path/to/jobcontrol", ["jobcontrol", arg1, arg2])
> -------------------------------
> 
> -------------------------------
> # this is from jobcontrol
> os.close (sys.stdin.fileno ())
> os.close (sys.stdout.fileno ())
> os.close (sys.stderr.fileno ())
> 
> logfile = open ("/path/to/logfile", "a")
> sys.stdout = sys.stderr = logfile
> mypid = os.getpid ()
> print "%d started: %s" % (mypid, repr(sys.argv))
> -------------------------------
> 
> Thanks for hints!
> 
> Bye,
>         Simon
> 
> --
>       Simon.Budig at unix-ag.org       http://www.home.unix-ag.org/simon/



More information about the Python-list mailing list