njouanin / hbmqtt

MQTT client/broker using Python asynchronous I/O
MIT License
795 stars 188 forks source link

Client connection close bug due to asyncio Task set_exception deprecated #208

Open shipmints opened 4 years ago

shipmints commented 4 years ago

set_exception was removed from asyncio some time ago per https://bugs.python.org/issue32363

The modern implementation, which simply pukes a RuntimeErrror...

def set_exception(self, exception):
        raise RuntimeError('Task does not support set_exception operation')

...causes handle_connection_close cancel_tasks loop to fail on the first set_exception call. It's not clear what this loop is trying to accomplish since it isn't canceling any pending tasks.

    @asyncio.coroutine
    def handle_connection_close(self):
        def cancel_tasks():
            self._no_more_connections.set()
            while self.client_tasks:
                task = self.client_tasks.popleft()
                if not task.done():
                    task.set_exception(ClientException("Connection lost")) # BOOM THE LOOP EXITS AND EXCEPTION PROPAGATED

Perhaps it should be?

        self._no_more_connections.set() // moved from above
        if self.config.get('auto_reconnect', False):
            # Try reconnection
            self.logger.debug("Auto-reconnecting")
            try:
                yield from self.reconnect()
            except ConnectException:
                # Cancel client pending tasks
                # REPLACE? cancel_tasks()
                yield from self.cancel_tasks()
        else:
            # Cancel client pending tasks
            # REPLACE? cancel_tasks()
            yield from self.cancel_tasks()
damouse commented 4 years ago

I'm running into the same problem. This causes deliver_message to hang instead of raising to indicate the connection closed.

Shipmint's suggestion above seems to fix the issue.

Zamony commented 2 years ago

I am getting the same error with hbmqtt==0.9.6