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