From 08b49b1c8b337d6f0fe0a268cdab6543fd0a3820 Mon Sep 17 00:00:00 2001 From: rndusr Date: Wed, 11 Oct 2023 09:37:02 +0000 Subject: [PATCH] LinuxDriver: Exit if thread dies (#3431) * LinuxDriver: Exit if thread dies If `run_input_thread()` dies, the whole application keeps running but becomes unresponsive. It has to be killed by the user, leaving the terminal in an unusable state. This commit terminates the application instead and prints a traceback. * LinuxDriver: Handle any exception from input thread * LinuxDriver: Simpler traceback construction in input thread handler * LinuxDriver: Catch exception from run_input_thread() in _run_input_thread() * LinuxDriver: Remove unneeded import: Callable --------- Co-authored-by: Random User --- src/textual/drivers/linux_driver.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/textual/drivers/linux_driver.py b/src/textual/drivers/linux_driver.py index c13512e8ab..c64f9dcdde 100644 --- a/src/textual/drivers/linux_driver.py +++ b/src/textual/drivers/linux_driver.py @@ -12,6 +12,7 @@ from typing import TYPE_CHECKING, Any import rich.repr +import rich.traceback from .. import events, log from .._xterm_parser import XTermParser @@ -164,7 +165,7 @@ def on_terminal_resize(signum, stack) -> None: self.write("\x1b[?25l") # Hide cursor self.write("\033[?1003h\n") self.flush() - self._key_thread = Thread(target=self.run_input_thread) + self._key_thread = Thread(target=self._run_input_thread) send_size_event() self._key_thread.start() self._request_terminal_sync_mode_support() @@ -233,6 +234,19 @@ def close(self) -> None: if self._writer_thread is not None: self._writer_thread.stop() + def _run_input_thread(self) -> None: + """ + Key thread target that wraps run_input_thread() to die gracefully if it raises + an exception + """ + try: + self.run_input_thread() + except BaseException as error: + self._app.call_later( + self._app.panic, + rich.traceback.Traceback(), + ) + def run_input_thread(self) -> None: """Wait for input and dispatch events.""" selector = selectors.DefaultSelector() @@ -264,7 +278,5 @@ def more_data() -> bool: unicode_data = decode(read(fileno, 1024)) for event in feed(unicode_data): self.process_event(event) - except Exception as error: - log(error) finally: selector.close()