Skip to content
Permalink
Browse files

core: wake Latch outside of lock.

Given:

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

Previously,

- 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

Now,

- 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 Feb 24, 2019
1 parent 7e51a93 commit 807cbef9caa374bbf96ac90a81221388345e832d
Showing with 4 additions and 1 deletion.
  1. +4 −1 mitogen/core.py
@@ -2489,17 +2489,20 @@ def put(self, obj=None):
raise LatchError()
self._queue.append(obj)

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:
self.notify(self)
finally:
self._lock.release()

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.
You can’t perform that action at this time.