From 5d8451ad1351df0c03253518ce6310510ddbdf95 Mon Sep 17 00:00:00 2001 From: Pierre Fersing Date: Sun, 7 Jan 2024 21:09:21 +0100 Subject: [PATCH 1/2] Correctly mark connection as broken on SSL error and don't crash loop_forever --- ChangeLog.txt | 2 ++ src/paho/mqtt/client.py | 22 +++++++++++----------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/ChangeLog.txt b/ChangeLog.txt index cb319ffe..2685de92 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -27,6 +27,8 @@ v2.0.0 - 2023-xx-xx and loop_start/loop_forever isn't used. Closes #525. - Fix wait_for_publish that could hang with QoS == 0 message on reconnection or publish during connection. Closes #549. +- Correctly mark connection as broken on SSL error and don't crash loop_forever. + Closes #750. v1.6.1 - 2021-10-21 diff --git a/src/paho/mqtt/client.py b/src/paho/mqtt/client.py index 50e74dec..14aed7cf 100644 --- a/src/paho/mqtt/client.py +++ b/src/paho/mqtt/client.py @@ -239,7 +239,7 @@ class _OutPacket(TypedDict): _socket = socket -class WebsocketConnectionError(ValueError): +class WebsocketConnectionError(ConnectionError): pass @@ -1909,7 +1909,7 @@ def loop_forever( if self._state == mqtt_cs_connect_async: try: self.reconnect() - except (OSError, WebsocketConnectionError): + except OSError: self._handle_on_connect_fail() if not retry_first_connection: raise @@ -1950,7 +1950,7 @@ def should_exit() -> bool: else: try: self.reconnect() - except (OSError, WebsocketConnectionError): + except OSError: self._handle_on_connect_fail() self._easy_log( MQTT_LOG_DEBUG, "Connection failed, retrying") @@ -2617,14 +2617,14 @@ def _packet_read(self) -> MQTTErrorCode: command = self._sock_recv(1) except BlockingIOError: return MQTTErrorCode.MQTT_ERR_AGAIN - except ConnectionError as err: - self._easy_log( - MQTT_LOG_ERR, 'failed to receive on socket: %s', err) - return MQTTErrorCode.MQTT_ERR_CONN_LOST except TimeoutError as err: self._easy_log( MQTT_LOG_ERR, 'timeout on socket: %s', err) return MQTTErrorCode.MQTT_ERR_CONN_LOST + except OSError as err: + self._easy_log( + MQTT_LOG_ERR, 'failed to receive on socket: %s', err) + return MQTTErrorCode.MQTT_ERR_CONN_LOST else: if len(command) == 0: return MQTTErrorCode.MQTT_ERR_CONN_LOST @@ -2639,7 +2639,7 @@ def _packet_read(self) -> MQTTErrorCode: byte = self._sock_recv(1) except BlockingIOError: return MQTTErrorCode.MQTT_ERR_AGAIN - except ConnectionError as err: + except OSError as err: self._easy_log( MQTT_LOG_ERR, 'failed to receive on socket: %s', err) return MQTTErrorCode.MQTT_ERR_CONN_LOST @@ -2669,7 +2669,7 @@ def _packet_read(self) -> MQTTErrorCode: data = self._sock_recv(self._in_packet['to_process']) except BlockingIOError: return MQTTErrorCode.MQTT_ERR_AGAIN - except ConnectionError as err: + except OSError as err: self._easy_log( MQTT_LOG_ERR, 'failed to receive on socket: %s', err) return MQTTErrorCode.MQTT_ERR_CONN_LOST @@ -2720,7 +2720,7 @@ def _packet_write(self) -> MQTTErrorCode: except BlockingIOError: self._out_packet.appendleft(packet) return MQTTErrorCode.MQTT_ERR_AGAIN - except ConnectionError as err: + except OSError as err: self._out_packet.appendleft(packet) self._easy_log( MQTT_LOG_ERR, 'failed to receive on socket: %s', err) @@ -4313,7 +4313,7 @@ def _recv_impl(self, length: int) -> bytes: else: raise BlockingIOError - except ConnectionError: + except OSError: self.connected = False return b'' From 8fa8596466539f06e37c1a4a82c8c5bece9c9158 Mon Sep 17 00:00:00 2001 From: Pierre Fersing Date: Sat, 13 Jan 2024 18:01:09 +0100 Subject: [PATCH 2/2] Don't break Websocket connection on BlockingIO & like error Previous commit catcher wider exception in WebsocketWrapper (OSError), which include temporary error like BlockingIOError, SSLWantReadError... This caused Websocket connection to break and cause client reconnection when it should only cause a later retry. Revert to catching previous ConnectionError, which should be fine, other fatal error like SSLEOFError that might happen would still be catched by caller (_sock_recv) which will take care of closing the websocket connection --- src/paho/mqtt/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/paho/mqtt/client.py b/src/paho/mqtt/client.py index 14aed7cf..4538d6c4 100644 --- a/src/paho/mqtt/client.py +++ b/src/paho/mqtt/client.py @@ -4313,7 +4313,7 @@ def _recv_impl(self, length: int) -> bytes: else: raise BlockingIOError - except OSError: + except ConnectionError: self.connected = False return b''