Open 57a92b3d-4509-44f6-960d-017b524a2a96 opened 5 years ago
Running python3.8 mp-bug-python2.8.py
usually gets stuck after a dozen iterations or so.
It appears that if I stop setting that signal handler it doesn't get stuck. Unfortunately I need it to perform critical cleanup.
This is what I got from gdb:
(gdb) py-bt
Traceback (most recent call first):
File "/usr/lib/python3.8/multiprocessing/synchronize.py", line 95, in __enter__
return self._semlock.__enter__()
File "/usr/lib/python3.8/multiprocessing/queues.py", line 355, in get
with self._rlock:
File "/usr/lib/python3.8/multiprocessing/pool.py", line 370, in worker
`func` and (a, b) becomes func(a, b).
File "/usr/lib/python3.8/multiprocessing/process.py", line 108, in run
self._target(*self._args, **self._kwargs)
File "/usr/lib/python3.8/multiprocessing/process.py", line 569, in _bootstrap
File "/usr/lib/python3.8/multiprocessing/popen_fork.py", line 75, in _launch
code = process_obj._bootstrap(parent_sentinel=child_r)
File "/usr/lib/python3.8/multiprocessing/popen_fork.py", line 19, in __init__
self._launch(process_obj)
File "/usr/lib/python3.8/multiprocessing/context.py", line 276, in _Popen
return Popen(process_obj)
File "/usr/lib/python3.8/multiprocessing/process.py", line 633, in start
File "/usr/lib/python3.8/multiprocessing/pool.py", line 838, in _repopulate_pool_static
self._length = None
File "/usr/lib/python3.8/multiprocessing/pool.py", line 559, in _repopulate_pool
outqueue.put(None)
File "/usr/lib/python3.8/multiprocessing/pool.py", line 212, in __init__
self._repopulate_pool()
File "/usr/lib/python3.8/multiprocessing/context.py", line 375, in Pool
File "mp-bug-python2.8.py", line 21, in <module>
And without the macros:
at ../Objects/descrobject.c:332
f=Frame 0x23ce820, for file /usr/lib/python3.8/multiprocessing/pool.py, line 370, in worker (inqueue=\<SimpleQueue(_reader=\<Connection(_handle=3, \_readable=True, \_writable=False) at remote 0x7f51c589dcd0\>, \_writer=\<Connection(_handle=None, \_readable=False, \_writable=True) at remote 0x7f51c589d940\>, \_rlock=\<Lock(_semlock=\<_multiprocessing.SemLock at remote 0x7f51c58a60b0\>, acquire=\<built-in method acquire of \_multiprocessing.SemLock object at remote 0x7f51c58a60b0\>, release=\<built-in method release of \_multiprocessing.SemLock object at remote 0x7f51c58a60b0\>) at remote 0x7f51c589d0d0\>, \_poll=\<method at remote 0x7f51c58ae2c0\>, \_wlock=\<Lock(_semlock=\<_multiprocessing.SemLock at remote 0x7f51c58a1030\>, acquire=\<built-in method acquire of \_multiprocessing.SemLock object at remote 0x7f51c58a1030\>, release=\<built-in method release of \_multiprocessing.SemLock object at remote 0x7f51c58a1030\>) at remote 0x7f51c589deb0\>) at remote 0x7f51c589d3a0\>, outqueue=\<SimpleQueue(_reader=\<Connection(_handle=None, \_readable=True, \_wr...(truncated))
at ../Python/ceval.c:741
defs=0x7f51c65a4828, defcount=4, kwdefs=0x0, closure=0x0, name='worker', qualname='worker') at ../Python/ceval.c:4298
callargs=(\<SimpleQueue(_reader=\<Connection(_handle=3, \_readable=True, \_writable=False) at remote 0x7f51c589dcd0\>, \_writer=\<Connection(_handle=None, \_readable=False, \_writable=True) at remote 0x7f51c589d940\>, \_rlock=\<Lock(_semlock=\<_multiprocessing.SemLock at remote 0x7f51c58a60b0\>, acquire=\<built-in method acquire of \_multiprocessing.SemLock object at remote 0x7f51c58a60b0\>, release=\<built-in method release of \_multiprocessing.SemLock object at remote 0x7f51c58a60b0\>) at remote 0x7f51c589d0d0\>, \_poll=\<method at remote 0x7f51c58ae2c0\>, \_wlock=\<Lock(_semlock=\<_multiprocessing.SemLock at remote 0x7f51c58a1030\>, acquire=\<built-in method acquire of \_multiprocessing.SemLock object at remote 0x7f51c58a1030\>, release=\<built-in method release of \_multiprocessing.SemLock object at remote 0x7f51c58a1030\>) at remote 0x7f51c589deb0\>) at remote 0x7f51c589d3a0\>, \<SimpleQueue(_reader=\<Connection(_handle=None, \_readable=True, \_writable=False) at remote 0x7f51c58a7670\>, \_writer=\<Connection(_handle=6, \_readable=False, \_writable=True) at...(truncated),
func=\<function at remote 0x7f51c6352d30\>, tstate=0x22bd160) at ../Python/ceval.c:5034
f=Frame 0x23e7f40, for file /usr/lib/python3.8/multiprocessing/process.py, line 569, in \_bootstrap (self=\<ForkProcess(_identity=(98,), \_config={'authkey': \<AuthenticationString at remote 0x7f51c66754c0\>, 'semprefix': '/mp', 'daemon': True}, \_parent_pid=191540, \_parent_name='MainProcess', \_popen=None, \_closed=False, \_target=\<function at remote 0x7f51c6352d30\>, \_args=(\<SimpleQueue(_reader=\<Connection(_handle=3, \_readable=True, \_writable=False) at remote 0x7f51c589dcd0\>, \_writer=\<Connection(_handle=None, \_readable=False, \_writable=True) at remote 0x7f51c589d940\>, \_rlock=\<Lock(_semlock=\<_multiprocessing.SemLock at remote 0x7f51c58a60b0\>, acquire=\<built-in method acquire of \_multiprocessing.SemLock object at remote 0x7f51c58a60b0\>, release=\<built-in method release of \_multiprocessing.SemLock object at remote 0x7f51c58a60b0\>) at remote 0x7f51c589d0d0\>, \_poll=\<method at remote 0x7f51c58ae2c0\>, \_wlock=\<Lock(_semlock=\<_multiprocessing.SemLock at remote 0x7f51c58a1030\>, acquire=\<built-in method acquire of \_multiprocessin...(truncated))
at ../Python/ceval.c:741
defs=0x7f51c6672808, defcount=1, kwdefs=0x0, closure=0x0, name='\_bootstrap', qualname='BaseProcess.\_bootstrap') at ../Python/ceval.c:4298
This issue doesn't reproduce on python 3.7 or earlier.
Several things here:
you can perform critical cleanup with the atexit module; using a signal handler for that is extremely low-level and error-prone
you can also try to switch to the "forkserver" method of multiprocessing, perhaps that will fix your issue
atexit proved time and time again to be unreliable, not really an option. Not all programs shutdown nicely enough for atexit.
Should I tell users "use forkserver on 3.8 because broken stuff"?
Looks like a duplicate of my previous issue
https://bugs.python.org/issue29759
Unfortunately some frameworks like Gunicorn are extensively using signal handlers for their internal purposes.
Reproducing issue with attached test (Python 3.8.2 on Ubuntu 16.04).
Attached working patch. Tested with signal handler set in Lib/test/_test_multiprocessing.py:
2329a2330,2331
def signal_handler(signum, frame): pass 2335a2338 cls.old_handler = signal.signal(signal.SIGTERM, signal_handler) 2342a2346 signal.signal(signal.SIGTERM, cls.old_handler)
All passing.
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields: ```python assignee = None closed_at = None created_at =
labels = ['3.8', 'library']
title = 'Setting a signal handler gets multiprocessing.Pool stuck'
updated_at =
user = 'https://bugs.python.org/ionelmc'
```
bugs.python.org fields:
```python
activity =
actor = 'wumpus'
assignee = 'none'
closed = False
closed_date = None
closer = None
components = ['Library (Lib)']
creation =
creator = 'ionelmc'
dependencies = []
files = ['48615', '49130', '49131']
hgrepos = []
issue_num = 38227
keywords = ['patch']
message_count = 6.0
messages = ['352815', '353938', '353947', '368233', '368234', '368237']
nosy_count = 4.0
nosy_names = ['pitrou', 'ionelmc', 'wumpus', 'mapozyan']
pr_nums = []
priority = 'normal'
resolution = None
stage = None
status = 'open'
superseder = None
type = None
url = 'https://bugs.python.org/issue38227'
versions = ['Python 3.8']
```