Skip to content
Browse files
core: wake Latch outside of lock.

- thread A asleep in Latch._get_sleep()
- thread B calling Latch.put()


- B takes lock,
- B wakes socket by dropping GIL and writing to it
- A wakes from poll(), acquires GIL only to find Latch._lock is held
- A drops GIL, sleeps on futex() for _lock
- B wakes, acquires GIL, releases _lock
- A wakes from futex(), acquires lock


- B takes lock, updates state, releases lock
- B wakes socket by droppping GIL and writing to it
- A wakes from poll(), acquires GIL and _lock
- Everyone lives happily ever after.
  • Loading branch information
dw committed Jul 29, 2019
1 parent 7e51a93 commit 807cbef9caa374bbf96ac90a81221388345e832d
Showing with 4 additions and 1 deletion.
  1. +4 −1 mitogen/
@@ -2489,17 +2489,20 @@ def put(self, obj=None):
raise LatchError()

wsock = None
if self._waking < len(self._sleeping):
wsock, cookie = self._sleeping[self._waking]
self._waking += 1
_vv and IOLOG.debug('%r.put() -> waking wfd=%r',
self, wsock.fileno())
self._wake(wsock, cookie)
elif self.notify:

if wsock:
self._wake(wsock, cookie)

def _wake(self, wsock, cookie):
written, disconnected = io_op(os.write, wsock.fileno(), cookie)
assert written == len(cookie) and not disconnected

0 comments on commit 807cbef

Please sign in to comment.