aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Lib/asyncio/base_events.py
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@gmail.com>2014-03-21 10:00:52 +0100
committerVictor Stinner <victor.stinner@gmail.com>2014-03-21 10:00:52 +0100
commit93569c2b3d48b36df80635dbe3c02e3d5baa00d7 (patch)
tree0b00d71b628b2fbd5e99caafb56e5a05b396614c /Lib/asyncio/base_events.py
parent4137465bf546964736e45bed16a15d05000b26e8 (diff)
downloadcpython-93569c2b3d48b36df80635dbe3c02e3d5baa00d7.tar.gz
cpython-93569c2b3d48b36df80635dbe3c02e3d5baa00d7.zip
asyncio: Ensure call_soon(), call_later() and call_at() are invoked on current
loop in debug mode. Raise a RuntimeError if the event loop of the current thread is different. The check should help to debug thread-safetly issue. Patch written by David Foster.
Diffstat (limited to 'Lib/asyncio/base_events.py')
-rw-r--r--Lib/asyncio/base_events.py23
1 files changed, 22 insertions, 1 deletions
diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py
index 80df9271b3b..d2bdc07d36c 100644
--- a/Lib/asyncio/base_events.py
+++ b/Lib/asyncio/base_events.py
@@ -259,6 +259,8 @@ class BaseEventLoop(events.AbstractEventLoop):
"""Like call_later(), but uses an absolute time."""
if tasks.iscoroutinefunction(callback):
raise TypeError("coroutines cannot be used with call_at()")
+ if self._debug:
+ self._assert_is_current_event_loop()
timer = events.TimerHandle(when, callback, args, self)
heapq.heappush(self._scheduled, timer)
return timer
@@ -273,15 +275,34 @@ class BaseEventLoop(events.AbstractEventLoop):
Any positional arguments after the callback will be passed to
the callback when it is called.
"""
+ return self._call_soon(callback, args, check_loop=True)
+
+ def _call_soon(self, callback, args, check_loop):
if tasks.iscoroutinefunction(callback):
raise TypeError("coroutines cannot be used with call_soon()")
+ if self._debug and check_loop:
+ self._assert_is_current_event_loop()
handle = events.Handle(callback, args, self)
self._ready.append(handle)
return handle
+ def _assert_is_current_event_loop(self):
+ """Asserts that this event loop is the current event loop.
+
+ Non-threadsafe methods of this class make this assumption and will
+ likely behave incorrectly when the assumption is violated.
+
+ Should only be called when (self._debug == True). The caller is
+ responsible for checking this condition for performance reasons.
+ """
+ if events.get_event_loop() is not self:
+ raise RuntimeError(
+ "non-threadsafe operation invoked on an event loop other "
+ "than the current one")
+
def call_soon_threadsafe(self, callback, *args):
"""XXX"""
- handle = self.call_soon(callback, *args)
+ handle = self._call_soon(callback, args, check_loop=False)
self._write_to_self()
return handle