mirror of
https://github.com/facebook/sapling.git
synced 2024-10-10 16:57:49 +03:00
ab49fe9698
Summary: As discussed, we want to make sure we have a good SocketServer for Python 2.6, which is unsupported by PSF but still being widely used by our users. This diff adds a new extension that tries to fix buggy Python standard modules, namely the SocketServer. It fixes a critical race condition for Python 2.6 (https://bugs.python.org/issue21491) and the zombie process issue for both Python 2.6 and 2.7 (https://bugs.python.org/issue11109). A simple test is added to check zombie processes are no more. Test Plan: Run the newly added test, `test-patchpython.py` with both Python 2.6 and 2.7. Comment out the `import patchpython` line in the test and make sure it fails on Python 2.6 and 2.7 with `AssertionError: zombie process detected`. Reviewers: #mercurial, ttung, mjpieters Reviewed By: mjpieters Subscribers: simonfar, durham, mjpieters Differential Revision: https://phabricator.intern.facebook.com/D3384909 Signature: t1:3384909:1465319491:0ba64b496186712651b7ee6bd502d1e2ccac57d1
65 lines
1.7 KiB
Python
65 lines
1.7 KiB
Python
import errno
|
|
import os
|
|
import signal
|
|
import socket
|
|
import sys
|
|
import time
|
|
try:
|
|
import SocketServer
|
|
except ImportError:
|
|
# Python 3
|
|
import socketserver as SocketServer
|
|
|
|
try:
|
|
import patchpython
|
|
except ImportError:
|
|
# This happens if run-tests.py is run from the "tests" directory
|
|
# instead of the root of the project.
|
|
sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))
|
|
import patchpython
|
|
|
|
def testnozombies():
|
|
class reportpidhandler(SocketServer.StreamRequestHandler):
|
|
def handle(self):
|
|
self.wfile.write('%s' % (os.getpid(),))
|
|
|
|
class server(SocketServer.ForkingMixIn, SocketServer.UnixStreamServer):
|
|
pass
|
|
|
|
socketpath = 'testsocket'
|
|
pid = os.fork()
|
|
|
|
if pid > 0:
|
|
# client
|
|
waittime = 0
|
|
while not os.path.exists(socketpath):
|
|
time.sleep(0.1)
|
|
waittime += 0.1
|
|
if waittime > 5:
|
|
assert False, 'server timed out'
|
|
try:
|
|
pids = []
|
|
for i in xrange(5):
|
|
s = socket.socket(socket.AF_UNIX)
|
|
s.connect(socketpath)
|
|
buf = s.recv(1024)
|
|
s.close()
|
|
pids.append(int(buf))
|
|
# give the server some time to do cleanup
|
|
time.sleep(0.5)
|
|
for p in pids:
|
|
try:
|
|
os.kill(p, 0)
|
|
assert False, 'zombie process detected'
|
|
except OSError as ex:
|
|
if ex.errno != errno.ESRCH:
|
|
raise
|
|
finally:
|
|
os.kill(pid, signal.SIGTERM) # stop server
|
|
else:
|
|
# server
|
|
s = server(socketpath, reportpidhandler)
|
|
s.serve_forever(poll_interval=0.1)
|
|
|
|
testnozombies()
|