Skip to content

Commit e5302e6

Browse files
committed
pythongh-126434: Use multiprocessing.Value for multiprocessing.Event to avoid deadlock when there is reentrant usage of set from is_set, e.g. when handling system signals
1 parent 78842e4 commit e5302e6

File tree

2 files changed

+14
-13
lines changed

2 files changed

+14
-13
lines changed

Lib/multiprocessing/synchronize.py

+13-13
Original file line numberDiff line numberDiff line change
@@ -329,34 +329,34 @@ class Event(object):
329329

330330
def __init__(self, *, ctx):
331331
self._cond = ctx.Condition(ctx.Lock())
332-
self._flag = ctx.Semaphore(0)
332+
self._flag = ctx.Value('i', 0)
333333

334334
def is_set(self):
335-
with self._cond:
336-
if self._flag.acquire(False):
337-
self._flag.release()
338-
return True
339-
return False
335+
return self._flag.value == 1
340336

341337
def set(self):
338+
assert not self._cond._lock._semlock._is_mine(), \
339+
'multiprocessing.Event is not reentrant for clear(), set() and wait()'
342340
with self._cond:
343-
self._flag.acquire(False)
344-
self._flag.release()
341+
self._flag.value = 1
345342
self._cond.notify_all()
346343

347344
def clear(self):
345+
assert not self._cond._lock._semlock._is_mine(), \
346+
'multiprocessing.Event is not reentrant for clear(), set() and wait()'
348347
with self._cond:
349-
self._flag.acquire(False)
348+
self._flag.value = 0
350349

351350
def wait(self, timeout=None):
351+
assert not self._cond._lock._semlock._is_mine(), \
352+
'multiprocessing.Event is not reentrant for clear(), set() and wait()'
352353
with self._cond:
353-
if self._flag.acquire(False):
354-
self._flag.release()
354+
if self._flag.value == 1:
355+
return True
355356
else:
356357
self._cond.wait(timeout)
357358

358-
if self._flag.acquire(False):
359-
self._flag.release()
359+
if self._flag.value == 1:
360360
return True
361361
return False
362362

Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Use :mod:`multiprocessing` ``Value`` for :mod:`multiprocessing` ``Event`` to avoid deadlock when reetrant usage of `set` from `is_set`, e.g. when handling system signals

0 commit comments

Comments
 (0)