From 9395b6b9bbdcd5bc12136a4b35d5cd300802c258 Mon Sep 17 00:00:00 2001 From: Logan Furedi Date: Tue, 30 Jun 2026 10:51:12 -0500 Subject: [PATCH] fix: proper quitting Ensure the program exits without stack traces when using q or Ctrl+C Note: Quitting can take up to 6 seconds since Urwid needs to free resources. Sometimes when hitting Ctrl+C, you may need to hit another key (such as an up or down arrow) to trigger the exit call (Not sure why this is). --- soti/umsats_soti/__main__.py | 2 ++ soti/umsats_soti/device.py | 56 ++++++++++++++++++++---------------- 2 files changed, 34 insertions(+), 24 deletions(-) diff --git a/soti/umsats_soti/__main__.py b/soti/umsats_soti/__main__.py index a04e7e2..22b96b8 100644 --- a/soti/umsats_soti/__main__.py +++ b/soti/umsats_soti/__main__.py @@ -28,6 +28,8 @@ def __init__(self): def run(self): try: self.loop.run() + except KeyboardInterrupt: + pass finally: self.current_screen.on_exit(self.loop) diff --git a/soti/umsats_soti/device.py b/soti/umsats_soti/device.py index 26e3320..677b5e3 100644 --- a/soti/umsats_soti/device.py +++ b/soti/umsats_soti/device.py @@ -56,23 +56,28 @@ def _run(self): print(f"[SerialDevice: {self.port}] Failed to open serial port: {e}") return - while True: - try: - msg = self._write_queue.get_nowait() - if msg is None: # Check for termination sentinel - break # Exit process - ser.write(msg.serialize()) - except queue.Empty: - pass - - # Read if bytes are available - if ser.in_waiting >= MSG_SIZE: - data = ser.read(MSG_SIZE) + try: + while True: try: - msg = Message.deserialize(data) - self._read_queue.put(msg) - except Exception as e: - print(f"[SerialDevice: {self.port}] Deserialization error: {e}") + msg = self._write_queue.get_nowait() + if msg is None: # Check for termination sentinel + break # Exit process + ser.write(msg.serialize()) + except queue.Empty: + pass + + # Read if bytes are available + if ser.in_waiting >= MSG_SIZE: + data = ser.read(MSG_SIZE) + try: + msg = Message.deserialize(data) + self._read_queue.put(msg) + except KeyboardInterrupt: + raise + except Exception as e: + print(f"[SerialDevice: {self.port}] Deserialization error: {e}") + except KeyboardInterrupt: + pass ser.close() @@ -81,11 +86,14 @@ class VirtualDevice(Device): """For when no device is selected.""" def _run(self): # Echo messages back to the user. - while True: - try: - msg = self._write_queue.get_nowait() - if msg is None: # Check for termination sentinel - break # Exit process - self._read_queue.put(msg) - except queue.Empty: - pass + try: + while True: + try: + msg = self._write_queue.get_nowait() + if msg is None: # Check for termination sentinel + break # Exit process + self._read_queue.put(msg) + except queue.Empty: + pass + except KeyboardInterrupt: + pass