Skip to content

Commit

Permalink
LinuxDriver: Exit if thread dies (#3431)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>
  • Loading branch information
rndusr and Random User authored Oct 11, 2023
1 parent e1c3800 commit 08b49b1
Showing 1 changed file with 15 additions and 3 deletions.
18 changes: 15 additions & 3 deletions src/textual/drivers/linux_driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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()

0 comments on commit 08b49b1

Please sign in to comment.