Search code examples
pythonexceptiontornado

Python tornado tornado.iostream.StreamClosedError


I have a python tornado websocket handler which works just fine. However, sporadically when tab is closed with websocket connection it throws exceptions which I can not catch. That occurs only with Firefox so I suspect that maybe it is some internal bug. Exception does not break execution of code but I still want to be able to catch all exceptions.

Exceptions:

ERROR:asyncio:Future exception was never retrieved future: Traceback (most recent call last): File "C:\Users\user\Anaconda3\lib\site-packages\tornado\websocket.py", line 808, in wrapper yield fut File "C:\Users\user\Anaconda3\lib\site-packages\tornado\gen.py", line 1099, in run value = future.result() tornado.iostream.StreamClosedError: Stream is closed

During handling of the above exception, another exception occurred:

Traceback (most recent call last): File "C:\Users\user\Anaconda3\lib\site-packages\tornado\gen.py", line 1107, in run yielded = self.gen.throw(*exc_info) File "C:\Users\user\Anaconda3\lib\site-packages\tornado\websocket.py", line 810, in wrapper raise WebSocketClosedError() tornado.websocket.WebSocketClosedError

An here is the code for the on_message function:

async def on_message(self, message):
    print(message)
    while True:
        try:
            #print('ws_connections: ', self.ws_connection, self.ws_connection.stream.socket)
            _fut = self.write_message(self.users[self].request_data())
        except tornado.iostream.StreamClosedError as e:
            print('StreamClosedError:', e)
            break
        except tornado.websocket.WebSocketClosedError as e:
            print('WebSocketClosedError:', e)
            break
        except KeyError as e:
            print('KeyError:', e)
            break
        await gen.sleep(1)

Solution

  • I found an answer in here: Catch errors in asyncio.ensure_future.

    async def on_message(self, message):
        print(message)
        while True:
            try:
                self.ping(b'ping')
                fut = self.write_message(self.users[self].request_data())
                await fut
            except tornado.iostream.StreamClosedError as e:
                print('StreamClosedError:', e)
                break
            except tornado.websocket.WebSocketClosedError as e:
                print('WebSocketClosedError:', self)
                break
            except KeyError as e:
                print('KeyError:', e)
                break
            await gen.sleep(5)
    

    I just needed to add 'await fut' after I returned future from self.write_message.