aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHornwitser <[email protected]>2015-09-27 16:15:29 +0200
committerHornwitser <[email protected]>2015-10-06 19:09:16 +0200
commit247d1f9ed4eea47013db14d6bd7e804ecff478eb (patch)
tree56cd5972886e5f408a0640dfe3aba2bf075d3d09
parentMove socket and connection state out of Client (diff)
downloaddiscord.py-247d1f9ed4eea47013db14d6bd7e804ecff478eb.tar.xz
discord.py-247d1f9ed4eea47013db14d6bd7e804ecff478eb.zip
Make dispatch multithreading safe
Guard the execution of dispatch with a recursive thread lock. This is needed to make a thread safe way to send events to Client objects. Note that the only thread safe method is dispatch, everything else is unsafe to call from another thread, as the thead handling the Client object could be modifying arbitrary structures at any time. In addition this only keeps nasal demons away, and does not solve any of the difficult syncronization issues that might be present.
-rw-r--r--discord/client.py26
1 files changed, 14 insertions, 12 deletions
diff --git a/discord/client.py b/discord/client.py
index 355a327d..cd5293f4 100644
--- a/discord/client.py
+++ b/discord/client.py
@@ -353,6 +353,7 @@ class Client(object):
def __init__(self, **kwargs):
self._is_logged_in = False
self.connection = ConnectionState(self.dispatch, **kwargs)
+ self.dispatch_lock = threading.RLock()
self.token = ''
self.events = {
'on_ready': _null_event,
@@ -435,18 +436,19 @@ class Client(object):
object.__setattr__(self, name, value)
def dispatch(self, event, *args, **kwargs):
- log.debug("Dispatching event {}".format(event))
- handle_method = '_'.join(('handle', event))
- event_method = '_'.join(('on', event))
- getattr(self, handle_method, _null_event)(*args, **kwargs)
- try:
- getattr(self, event_method, _null_event)(*args, **kwargs)
- except Exception as e:
- getattr(self, 'on_error')(event_method, *args, **kwargs)
-
- # Compatibility shim to old event system.
- if event_method in self.events:
- self._invoke_event(event_method, *args, **kwargs)
+ with self.dispatch_lock:
+ log.debug("Dispatching event {}".format(event))
+ handle_method = '_'.join(('handle', event))
+ event_method = '_'.join(('on', event))
+ getattr(self, handle_method, _null_event)(*args, **kwargs)
+ try:
+ getattr(self, event_method, _null_event)(*args, **kwargs)
+ except Exception as e:
+ getattr(self, 'on_error')(event_method, *args, **kwargs)
+
+ # Compatibility shim to old event system.
+ if event_method in self.events:
+ self._invoke_event(event_method, *args, **kwargs)
def _invoke_event(self, event_name, *args, **kwargs):
try: