From a9e990fd929822984bc67dd3ed3061efce8472d1 Mon Sep 17 00:00:00 2001 From: Oliver Facklam Date: Thu, 16 Apr 2026 18:04:38 +0200 Subject: [PATCH] fix(serial): during auto-reconnect, update all pySerial references The previous implementation of the auto-reconnection feature (commit 019e38a97d9d0be88569c50bd1426191a6f69010) detects connection loss in the reader _event_loop() and proceeds to re-assign the local variable to a fresh pySerial instance. However, the `proc` member of the Serial class is not updated, and attempts to write to the Serial instance continue to fail even after the reconnection logic succeeded. Therefore, make _SerialRedirectThread take the Serial instance as argument, instead of the pySerial.Serial object. The _event_loop() can thus operate on and update the `proc` member directly. --- .../pytest_embedded_serial/serial.py | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/pytest-embedded-serial/pytest_embedded_serial/serial.py b/pytest-embedded-serial/pytest_embedded_serial/serial.py index 8ab70195..ebcb4cad 100644 --- a/pytest-embedded-serial/pytest_embedded_serial/serial.py +++ b/pytest-embedded-serial/pytest_embedded_serial/serial.py @@ -108,7 +108,7 @@ def start_redirect_thread(self) -> None: # Here the reason why we're still using thread is, # the `pyserial` object can't be pickled when using multiprocessing.Process - self._redirect_thread = _SerialRedirectThread(self._q, self.proc) + self._redirect_thread = _SerialRedirectThread(self._q, self) self._redirect_thread.start() def stop_redirect_thread(self) -> bool: @@ -168,7 +168,7 @@ class _SerialRedirectThread(threading.Thread): Redirect serial thread """ - def __init__(self, msg_queue: MessageQueue, s: pyserial.Serial): + def __init__(self, msg_queue: MessageQueue, s: Serial): self._q = msg_queue self._event_q = multiprocessing.Queue() self._s = s @@ -196,22 +196,22 @@ def _event_loop(self): continue try: - s = self._s.read_all() + s = self._s.proc.read_all() except OSError as e: logging.error(f'OSError detected: {e}. Serial connection may be lost.') - if self._s.closed: + if self._s.proc.closed: logging.error('Serial port is already closed. Exiting event loop.') return - port = self._s.port + port = self._s.proc.port port_config = { - 'baudrate': self._s.baudrate, - 'bytesize': self._s.bytesize, - 'parity': self._s.parity, - 'stopbits': self._s.stopbits, - 'timeout': self._s.timeout, - 'xonxoff': self._s.xonxoff, - 'rtscts': self._s.rtscts, + 'baudrate': self._s.proc.baudrate, + 'bytesize': self._s.proc.bytesize, + 'parity': self._s.proc.parity, + 'stopbits': self._s.proc.stopbits, + 'timeout': self._s.proc.timeout, + 'xonxoff': self._s.proc.xonxoff, + 'rtscts': self._s.proc.rtscts, } for attempt in range(1, 4): delay = attempt * 1.5 @@ -220,8 +220,8 @@ def _event_loop(self): ) time.sleep(delay) try: - self._s.close() - self._s = pyserial.serial_for_url(port, **port_config) + self._s.proc.close() + self._s.proc = pyserial.serial_for_url(port, **port_config) logging.info(f'Successfully reconnected to serial port {port}.') break except Exception as e: