Browse Source

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.
pull/9/head
Hornwitser 10 years ago
parent
commit
247d1f9ed4
  1. 26
      discord/client.py

26
discord/client.py

@ -353,6 +353,7 @@ class Client(object):
def __init__(self, **kwargs): def __init__(self, **kwargs):
self._is_logged_in = False self._is_logged_in = False
self.connection = ConnectionState(self.dispatch, **kwargs) self.connection = ConnectionState(self.dispatch, **kwargs)
self.dispatch_lock = threading.RLock()
self.token = '' self.token = ''
self.events = { self.events = {
'on_ready': _null_event, 'on_ready': _null_event,
@ -435,18 +436,19 @@ class Client(object):
object.__setattr__(self, name, value) object.__setattr__(self, name, value)
def dispatch(self, event, *args, **kwargs): def dispatch(self, event, *args, **kwargs):
log.debug("Dispatching event {}".format(event)) with self.dispatch_lock:
handle_method = '_'.join(('handle', event)) log.debug("Dispatching event {}".format(event))
event_method = '_'.join(('on', event)) handle_method = '_'.join(('handle', event))
getattr(self, handle_method, _null_event)(*args, **kwargs) event_method = '_'.join(('on', event))
try: getattr(self, handle_method, _null_event)(*args, **kwargs)
getattr(self, event_method, _null_event)(*args, **kwargs) try:
except Exception as e: getattr(self, event_method, _null_event)(*args, **kwargs)
getattr(self, 'on_error')(event_method, *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: # Compatibility shim to old event system.
self._invoke_event(event_method, *args, **kwargs) if event_method in self.events:
self._invoke_event(event_method, *args, **kwargs)
def _invoke_event(self, event_name, *args, **kwargs): def _invoke_event(self, event_name, *args, **kwargs):
try: try:

Loading…
Cancel
Save