Skip to content

Commit

Permalink
In add_callback, hold the lock while writing to the waker pipe.
Browse files Browse the repository at this point in the history
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 tornadoweb#875.
  • Loading branch information
bdarnell committed Aug 19, 2013
1 parent 6ec711c commit 8e7effd
Showing 1 changed file with 8 additions and 8 deletions.
16 changes: 8 additions & 8 deletions tornado/ioloop.py
Original file line number Diff line number Diff line change
Expand Up @@ -722,14 +722,14 @@ def add_callback(self, callback, *args, **kwargs):
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():
Expand Down

0 comments on commit 8e7effd

Please sign in to comment.