[New-bugs-announce] [issue10636] subprocess module has race condition with SIGCHLD handlers

joseph.h.garvin report at bugs.python.org
Mon Dec 6 01:19:56 CET 2010

New submission from joseph.h.garvin <joseph.h.garvin at gmail.com>:

The following code will result in a traceback 99% of the time, though it may take two runs (sometimes the first run won't trigger it, I think due to the changing in timing from genrating the .pyc file). It spawns an instance of /bin/echo, chosen because it's a very quick to finish program. Any program that executes faster than subprocess.Popen can return will work as a substitute though:

import signal
import subprocess

to_launch = None

def sig_chld_handler(signum, frame):
    global to_launch
    # Crashes here.
    # 'NoneType' object has no attribute 'poll'

    print to_launch.returncode

signal.signal(signal.SIGCHLD, sig_chld_handler)

to_launch = subprocess.Popen("/bin/echo")

And the traceback:

Traceback (most recent call last):
  File "/tmp/sigchld.py", line 15, in <module>
    to_launch = subprocess.Popen("/bin/echo")
  File "/usr/lib/python2.6/subprocess.py", line 623, in __init__
    errread, errwrite)
  File "/usr/lib/python2.6/subprocess.py", line 1130, in _execute_child
    data = _eintr_retry_call(os.read, errpipe_read, 1048576)
  File "/usr/lib/python2.6/subprocess.py", line 455, in _eintr_retry_call
    return func(*args)
  File "/tmp/sigchld.py", line 9, in sig_chld_handler
AttributeError: 'NoneType' object has no attribute 'poll'

I believe the problem is that the process completes before Popen can return, which means the assignment of to_launch hasn't happened yet, so it's not defined when we get into sig_chld_handler.

I tried to work around this issue by setting preexec_fn to signal.pause and sending the child process a signal after the assignment, but then ran into another bug: http://bugs.python.org/issue10635

If when it caught SIGCHLD python pushed an event onto its internal event loop to execute the handler, I think that would make sure it's deferred until after the assignment. There might be other consequences of that, but I'm not familiar with the interpreter internals. Alternatively it could be fixed with an API change -- let Popen return an object before it actually launches the process, and have a separate start() method.

components: Library (Lib)
messages: 123445
nosy: joseph.h.garvin
priority: normal
severity: normal
status: open
title: subprocess module has race condition with SIGCHLD handlers
versions: Python 2.6

Python tracker <report at bugs.python.org>

More information about the New-bugs-announce mailing list