Browse Source

Fix keep_alive running after logout()

_keep_alive_handler would set up another keep alive after the first one
by creating a new threading.Timer object, but Client would only keep
track of the first timer object.  Thus casing the keep alive to continue
running after Client.logout calls cancel() on it's timer object, as it
no longer references the actual timer object waiting for the keep alive.

Fix by replacing _keep_alive_handler with a threading.Thread subclass
that sends keep_alives of the given interval and exits when its stop
event is set.
pull/3/head
Hornwitser 10 years ago
parent
commit
a4c152cebc
  1. 34
      discord/client.py

34
discord/client.py

@ -36,7 +36,7 @@ from .invite import Invite
import requests import requests
import json, re, time, copy import json, re, time, copy
from collections import deque from collections import deque
from threading import Timer import threading
from ws4py.client.threadedclient import WebSocketClient from ws4py.client.threadedclient import WebSocketClient
import sys import sys
import logging import logging
@ -48,20 +48,23 @@ request_success_log = '{name}: {response.url} with {json} received {data}'
def _null_event(*args, **kwargs): def _null_event(*args, **kwargs):
pass pass
def _keep_alive_handler(seconds, ws): class KeepAliveHandler(threading.Thread):
def wrapper(): def __init__(self, seconds, socket, **kwargs):
_keep_alive_handler(seconds, ws) threading.Thread.__init__(self, **kwargs)
payload = { self.seconds = seconds
'op': 1, self.socket = socket
'd': int(time.time()) self.stop = threading.Event()
}
log.debug('Keeping websocket alive with timestamp {0}'.format(payload['d'])) def run(self):
ws.send(json.dumps(payload)) while not self.stop.wait(self.seconds):
payload = {
'op': 1,
'd': int(time.time())
}
t = Timer(seconds, wrapper) msg = 'Keeping websocket alive with timestamp {0}'
t.start() log.debug(msg.format(payload['d']))
return t self.socket.send(json.dumps(payload))
class Client(object): class Client(object):
"""Represents a client connection that connects to Discord. """Represents a client connection that connects to Discord.
@ -229,7 +232,8 @@ class Client(object):
# set the keep alive interval.. # set the keep alive interval..
interval = data.get('heartbeat_interval') / 1000.0 interval = data.get('heartbeat_interval') / 1000.0
self.keep_alive = _keep_alive_handler(interval, self.ws) self.keep_alive = KeepAliveHandler(interval, self.ws)
self.keep_alive.start()
# we're all ready # we're all ready
self._invoke_event('on_ready') self._invoke_event('on_ready')
@ -553,7 +557,7 @@ class Client(object):
response = requests.post(endpoints.LOGOUT) response = requests.post(endpoints.LOGOUT)
self.ws.close() self.ws.close()
self._is_logged_in = False self._is_logged_in = False
self.keep_alive.cancel() self.keep_alive.stop.set()
log.debug(request_logging_format.format(name='logout', response=response)) log.debug(request_logging_format.format(name='logout', response=response))
def logs_from(self, channel, limit=500): def logs_from(self, channel, limit=500):

Loading…
Cancel
Save