From 93da1da3867f0bc9010b93e54e75b352dc51feb9 Mon Sep 17 00:00:00 2001 From: SpudGunMan Date: Tue, 14 Oct 2025 07:42:27 -0700 Subject: [PATCH 1/2] flush() is only called if the stream is open This ensures flush() is only called if the stream is open, and logs (but ignores) any exceptions during flush. This should prevent the "Bad file descriptor" error. I see this error a lot on a rak unit, I dont know this is the way but .. you be the judge. --- meshtastic/serial_interface.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/meshtastic/serial_interface.py b/meshtastic/serial_interface.py index a9d5dd70a..ef4eeaf68 100644 --- a/meshtastic/serial_interface.py +++ b/meshtastic/serial_interface.py @@ -85,10 +85,14 @@ def __repr__(self): def close(self) -> None: """Close a connection to the device""" - if self.stream: # Stream can be null if we were already closed - self.stream.flush() # FIXME: why are there these two flushes with 100ms sleeps? This shouldn't be necessary - time.sleep(0.1) - self.stream.flush() - time.sleep(0.1) + if hasattr(self, "stream") and self.stream and getattr(self.stream, "is_open", False): + try: + self.stream.flush() + time.sleep(0.1) + # FIXME: why are there these two flushes with 100ms sleeps? This shouldn't be necessary + self.stream.flush() + time.sleep(0.1) + except Exception as e: + logger.debug(f"Exception during flush: {e}") logger.debug("Closing Serial stream") StreamInterface.close(self) From da416fcd20dd59a11721a92f0d64c62ee4b95aa2 Mon Sep 17 00:00:00 2001 From: SpudGunMan Date: Tue, 14 Oct 2025 07:54:37 -0700 Subject: [PATCH 2/2] refactor flush The double flush() is not the root cause; the real issue is that code is trying to use the serial port after it has been closed. The error occurs both in close() (during flush()) and later in _writeBytes() (during write()), indicating the port is closed or invalid at those times. --- meshtastic/serial_interface.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/meshtastic/serial_interface.py b/meshtastic/serial_interface.py index ef4eeaf68..e3b740015 100644 --- a/meshtastic/serial_interface.py +++ b/meshtastic/serial_interface.py @@ -89,10 +89,12 @@ def close(self) -> None: try: self.stream.flush() time.sleep(0.1) - # FIXME: why are there these two flushes with 100ms sleeps? This shouldn't be necessary - self.stream.flush() - time.sleep(0.1) except Exception as e: logger.debug(f"Exception during flush: {e}") + try: + self.stream.close() + except Exception as e: + logger.debug(f"Exception during close: {e}") + self.stream = None logger.debug("Closing Serial stream") StreamInterface.close(self)