mitogen: Kill (hung) bootstrap processes after 5 second timeout

Since using select.select() in the first stage (to handle an obscure corner
case where stdin appears to be non-blocking) there has been a report of first
stage processes running for ever in an infinite loop - reading 0 bytes from
stdin.

This attempts to do an end run around that problem by aborting if the
bootstrap takes longer than a few seconds for *any* reason. Existing retry
logic should deal with it as before.

5 seconds is a best guess at a suitable timeout.
pull/1349/head
Alex Willmer 1 month ago
parent 82a0efcb31
commit 03a0a151ff

@ -21,6 +21,9 @@ To avail of fixes in an unreleased version, please download a ZIP file
In progress (unreleased)
------------------------
* :gh:issue:`1266` :mod:`mitogen`: Prevent hung bootstrap processes, add 5
second timeout to first stage
v0.3.34 (2025-11-27)
--------------------

@ -1436,6 +1436,10 @@ class Connection(object):
if os.uname()[0]+os.uname()[2][:2]+sys.version[:3]=='Darwin212.7':os.environ['PYTHON_LAUNCHED_FROM_WRAPPER']='1'
os.environ['ARGV0']=sys.executable
os.execl(sys.executable,sys.executable+'(mitogen:%s)'%sys.argv[2])
# Timeout execution after a few seconds, to prevent hung processes.
# Cause might be closed/reset pipe/stream backing stdin (fd=0);
# or blocking write to interpreter stdin (fd=W, fd=w).
signal.alarm(5)
os.write(1,'MITO000\n'.encode())
C=''.encode()
while int(sys.argv[3])-len(C)and select.select([0],[],[]):C+=os.read(0,int(sys.argv[3])-len(C))
@ -1476,11 +1480,11 @@ class Connection(object):
# Just enough to decode, decompress, and exec the first stage.
# Priorities: wider compatibility, faster startup, shorter length.
# `sys.path=...` for https://github.com/python/cpython/issues/115911.
# `import os,select` here (not stage 1) to save a few bytes overall.
# `import os,...` here (not stage 1) saves a few bytes overall.
return self.get_python_argv() + [
'-c',
'import sys;sys.path=[p for p in sys.path if p];'
'import binascii,os,select,zlib;'
'import binascii,os,select,signal,zlib;'
'exec(zlib.decompress(binascii.a2b_base64(sys.argv[1]),-15))',
encoded.decode(),
self.options.remote_name,

Loading…
Cancel
Save