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.
pull/607/head
David Wilson 5 years ago
parent 7e51a93231
commit 807cbef9ca

@ -2489,17 +2489,20 @@ class Latch(object):
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

Loading…
Cancel
Save