From d6faff06c1a60c6d95486ada12c65749f403cf2d Mon Sep 17 00:00:00 2001 From: David Wilson Date: Sun, 24 Feb 2019 20:09:48 +0000 Subject: [PATCH] core: wake Waker outside of lock. Given: - Broker asleep in poll() - thread B calling Latch.put() Previously, - B takes lock, - B wakes socket by dropping GIL and writing to it - Broker wakes from poll(), acquires GIL only to find Latch._lock is held - Broker drops GIL, sleeps on futex() for _lock - B wakes, acquires GIL, releases _lock - Broker wakes from futex(), acquires lock Now, - B takes lock, updates state, releases lock - B wakes socket by droppping GIL and writing to it - Broker wakes from poll(), acquires GIL and _lock - Everyone lives happily ever after. --- mitogen/core.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mitogen/core.py b/mitogen/core.py index ea55f7bb..f850def9 100644 --- a/mitogen/core.py +++ b/mitogen/core.py @@ -2613,12 +2613,14 @@ class Waker(Protocol): self.stream.transmit_side.fd) self._lock.acquire() try: - if not self._deferred: - self._wake() + should_wake = not self._deferred self._deferred.append((func, args, kwargs)) finally: self._lock.release() + if should_wake: + self._wake() + class IoLoggerProtocol(DelimitedProtocol): """