You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Subprocess.wait_for_exit never resolves if process terminated before it is called #3364
The wait_for_exit method eventually calls os.waitpid, which throws a ChildProcessError if no process with the specified pid exists. This exception is caught, the function just returns, and the Future never resolves.
As long as Tornado is the only thing that touches the SIGCHLD handler, the child process is guaranteed to exist (in a zombie state) until os.waitpid (or another wait function) is called on it once. Could something else be installing a SIGCHLD handler, ignoring SIGCHLD, or calling os.wait directly? (In this example it seems wrong to use both p.proc.wait() and p.wait_for_exit() but if you've seen it in the wild I doubt it's that simple)
Ok, interesting! As far as I understand, nothing else is happening. We were creating the subprocess (calling git init) and immediately called wait_for_exit on the following line.
However, we used the Subprocess class outside the tornado process (in a Celery worker instance). Could this have anything to do with it? We have now switched to Popen and wait, which works as intended. The docs don't mention anything about this.
However, we used the Subprocess class outside the tornado process (in a Celery worker instance).
I'm confused (maybe because I've never used celery) - there's still a tornado IOLoop (or asyncio event loop) running in the worker process, right? If not you wouldn't be able to await p.wait_for_exit().
Celery does touch the SIGCLD handler although I'm not sure if it's possible for this to be run in a way that would clobber tornado's SIGCLD handler. It doesn't appear to call asyncio's set_child_watcher function but if something in the stack does, it could also cause this problem.
Activity
bdarnell commentedon Mar 3, 2024
As long as Tornado is the only thing that touches the SIGCHLD handler, the child process is guaranteed to exist (in a zombie state) until os.waitpid (or another wait function) is called on it once. Could something else be installing a SIGCHLD handler, ignoring SIGCHLD, or calling os.wait directly? (In this example it seems wrong to use both
p.proc.wait()andp.wait_for_exit()but if you've seen it in the wild I doubt it's that simple)meffmadd commentedon Mar 4, 2024
Ok, interesting! As far as I understand, nothing else is happening. We were creating the subprocess (calling
git init) and immediately calledwait_for_exiton the following line.However, we used the
Subprocessclass outside the tornado process (in a Celery worker instance). Could this have anything to do with it? We have now switched toPopenandwait, which works as intended. The docs don't mention anything about this.bdarnell commentedon Jun 13, 2024
I'm confused (maybe because I've never used celery) - there's still a tornado IOLoop (or asyncio event loop) running in the worker process, right? If not you wouldn't be able to
await p.wait_for_exit().Celery does touch the SIGCLD handler although I'm not sure if it's possible for this to be run in a way that would clobber tornado's SIGCLD handler. It doesn't appear to call asyncio's
set_child_watcherfunction but if something in the stack does, it could also cause this problem.