It's just magic, and I hate it ...

Mitchell Morris mgm at unpkhswm04.bscc.bls.com
Wed Jun 23 20:41:36 CEST 1999


As much as I hate to admit I'm an idiot, I got caught by the simplest of
things. When the child forks, it inherits all the open file descriptors of
the parent ... which includes sys.stdin and sys.stdout. Since these two (at
least) are attached to the socket from the browser, the browser doesn't
follow the redirect until *ALL* the fds close.

My new question is how do I close all the connections to the browser after
the fork? The obvious:
	sys.stdin.close()
	sys.stdout.close()
	sys.stderr.close()
didn't get them all, since the browser continues to wait. Is there a
mechanism to determine all opened files?




To recap, here is the offending source

#! /usr/bin/env python

import sys
import cgi
import time
import os
import string
import socket

form = cgi.FieldStorage()
if form.has_key("title"):
	hostname = socket.gethostbyaddr(socket.gethostname())[0]
	uniq = hex(os.getpid())[2:] + hex(int(time.time()))[2:]
	addr = "http://%s/~mgm/results/%s.html" % (hostname, uniq)
	fn = "/home/mgm/public_html/results/%s.html" % uniq

	# Generate the results file
	open(fn, "w").write("""<HTML>
<HEAD>
<META HTTP-EQUIV=REFRESH CONTENT=5>
<TITLE>Results for [%s]</TITLE>
</HEAD>
<BODY>
<P>Beginning search at %s:
</BODY>
</HTML>
""" % (form["title"].value, time.asctime(time.localtime(time.time()))))

	# Parent returns a redirect, child pretends to work for a while
	# accumulating results
	if os.fork() == 0:
		sys.stdin.close()
		sys.stdout.close()
		sys.stderr.close()
		for i in (1, 2, 3):
			txt = open(fn, 'r').readlines()
			txt.insert(len(txt)-2, "<P>Still searching\n")
			open(fn, 'w').write(string.join(txt, ''))
			time.sleep(10)
		open(fn, 'w').write("""<HTML>
<HEAD>
<TITLE>Finished</TITLE>
</HEAD>
<BODY>
<H1>Finished</H1>
<P>If you had results, they'd be here
</BODY>
</HTML>
""")
	else:
		print "Status: 302 Moved"
		print "Location:", addr
else:
	print """Content-type: text/html

<HTML>
<HEAD>
<TITLE>Sample Form</TITLE>
</HEAD>
<BODY>
<P>
<H1>Sample Form</H1>
<FORM METHOD="POST">
Title: <INPUT TYPE="TEXT" NAME="title"><P>
<INPUT TYPE="SUBMIT" NAME="submit">
</FORM>
</BODY>
</HTML>"""


-- 
Mitchell Morris

If at first you don't succeed, see if the loser gets anything.




More information about the Python-list mailing list