]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
In add_callback, hold the lock while writing to the waker pipe.
authorBen Darnell <ben@bendarnell.com>
Mon, 19 Aug 2013 03:54:59 +0000 (23:54 -0400)
committerBen Darnell <ben@bendarnell.com>
Mon, 19 Aug 2013 03:54:59 +0000 (23:54 -0400)
This protects against a shutdown race condition seen occasionally in
the ThreadedResolver unittests.  This slightly increases contention
on the callback lock in multi-threaded scenarios, but the cost is
limited by the fact that we only write to the pipe once per IOLoop
iteration.

Closes #875.

tornado/ioloop.py

index c9f2e47c534ad5cefafb462169ddfe19f19c4e32..a36ab7a594f8d0c5474a1c8ded5d7162714d0de9 100644 (file)
@@ -722,14 +722,14 @@ class PollIOLoop(IOLoop):
             list_empty = not self._callbacks
             self._callbacks.append(functools.partial(
                 stack_context.wrap(callback), *args, **kwargs))
-        if list_empty and thread.get_ident() != self._thread_ident:
-            # If we're in the IOLoop's thread, we know it's not currently
-            # polling.  If we're not, and we added the first callback to an
-            # empty list, we may need to wake it up (it may wake up on its
-            # own, but an occasional extra wake is harmless).  Waking
-            # up a polling IOLoop is relatively expensive, so we try to
-            # avoid it when we can.
-            self._waker.wake()
+            if list_empty and thread.get_ident() != self._thread_ident:
+                # If we're in the IOLoop's thread, we know it's not currently
+                # polling.  If we're not, and we added the first callback to an
+                # empty list, we may need to wake it up (it may wake up on its
+                # own, but an occasional extra wake is harmless).  Waking
+                # up a polling IOLoop is relatively expensive, so we try to
+                # avoid it when we can.
+                self._waker.wake()
 
     def add_callback_from_signal(self, callback, *args, **kwargs):
         with stack_context.NullContext():