websocket-client: on_close() doesn't get called after calling close()

code just like:

class MyWS(object):
    def __init__(self):
        self._ws = None
    def on_close(self):
        print("closed")

    def run(self):
        try:
            # websocket.enableTrace(True)
            self._ws = websocket.WebSocketApp(*******)
            self._ws.on_close = self.on_close
            self._ws.run_forever()
        except Exception:
            pass

After calling run() above and connection successful, I call self._ws.close() somewhere, But on_close() func doesn’t get called. What’s wrong? In _app.py:

    def close(self, **kwargs):
        """
        close websocket connection.
        """
        self.keep_running = False
        if self.sock:
            self.sock.close(**kwargs)
            self.sock = None

As above, After calling self._ws.close(), self.keep_running is set to False, Then in _app.py:

class Dispatcher:
    def __init__(self, app, ping_timeout):
        self.app = app
        self.ping_timeout = ping_timeout

    def read(self, sock, read_callback, check_callback):
        while self.app.keep_running:
            r, w, e = select.select(
                    (self.app.sock.sock, ), (), (), self.ping_timeout)
            if r:
                if not read_callback():
                    break
            check_callback()

the while loop in read() func will be over according to self.keep_running. After dispatcher.read(), nothing is going to be done in run_forever() func.

Is there some suggestions? Thks.

About this issue

  • Original URL
  • State: open
  • Created 4 years ago
  • Comments: 19 (1 by maintainers)

Most upvoted comments

FYI for everyone here. I might have fixed this bug while actually hunting another issue, as you can see in the PR above. I would love to hear if this bug is resokved in 1.6.0!

The same issue with me, I had to downgrade to 0.54.0

Thank you very much for fixing it @QuinnDamerell ! I had this issue in my code without knowing why the on_close() doesn’t set an important event. It drove me almost nuts, since I hadn’t found anything relevant when I first searched for the problem back almost a month ago. Recently tried again, found this and now my code works properly! Big thanks!

Thank you very much @QuinnDamerell and @engn33r ! I plan to test your fix in the following weeks and I’ll let you know.

You’re right, I’m an idiot! Thanks for this very nice answer.

FYI, in my tests after your fix, the “closed” is printing with KeyboardInterrupt and using Thread

>>> import websocket
>>> from threading import Thread
>>>
>>> def on_close(wsapp):
...     print("closed for real")
>>>
>>> wsapp = websocket.WebSocketApp("ws://echo.websocket.org", on_close=on_close)
>>> t = Thread(target=wsapp.run_forever)
>>> t.start()
>>> wsapp.close()
closed for real

Same issue after upgrading to 0.57.0. Went back to 0.40.0 and all worked fine again.