|
It's way harder than it should be to have a CGI script do something
asynchronously in Apache. The root of the problem is that it's not
enough to fork a child, you have to close stdin, stdout, and stderr.
Only you can't really close them, you have to reassign them.
import sys, os, time
print "Content-Type: text/plain\n\n",
print "Script started"
if os.fork() == 0:
# Reassign stdin, stdout, stderr for child
# so Apache will ignore it
si = file('/dev/null', 'r')
so = file('/dev/null', 'a+')
se = file('/dev/null', 'a+', 0)
os.dup2(si.fileno(), sys.stdin.fileno())
os.dup2(so.fileno(), sys.stdout.fileno())
os.dup2(se.fileno(), sys.stderr.fileno())
# Do whatever you want asynchronously
time.sleep(2)
os.execv('/bin/sleep', ['sleep', '5'])
print "Process was forked"
This is explained pretty well
in
Perl and in
Python. It's a shame that sys.stdin.close() doesn't work.
I still haven't seen a good explanation for why Apache doesn't send partial output from a CGI: Apache says it doesn't buffer and neither does python -u. Grr. Ah ha, mod_gzip does buffer, unsurprisingly. Thanks to Marc for research help
|
||