mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-10-24 04:39:06 -05:00
fix: keep a crash log for a card read error
Any EIO was read as the window closing, so a failing SD card ended the interface with 129 and no error.log. The error now counts as a closed window only once the terminal itself no longer answers tcgetattr.
This commit is contained in:
1 parent
76da554da9
commit
bc4bcadcd3
2 files changed
+45
-6
No files matched your search
+22
-6
@@ -12966,7 +12966,7 @@ def run_tui(args: argparse.Namespace) -> int:
|
||||
# The result is printed in the terminal on the way out.
|
||||
state.exit_code = state.code if state.code is not None else 1
|
||||
except Exception as exc: # noqa: BLE001
|
||||
if flags["term"] or _closed_terminal(exc):
|
||||
if flags["term"] or _closed_terminal(exc, terminal.fd):
|
||||
# The window closed under a screen that was changing, or the
|
||||
# SIGCONT that comes with its SIGHUP put the screen back: the
|
||||
# write failed before the signal was read. That is its exit.
|
||||
@@ -13030,13 +13030,29 @@ def _tui_startup(args: argparse.Namespace) -> tuple[TuiState, list[tuple]] | Non
|
||||
_CLOSED_TERMINAL = frozenset({errno.EIO, errno.EPIPE, errno.ENXIO})
|
||||
|
||||
|
||||
def _closed_terminal(exc: BaseException) -> bool:
|
||||
def _closed_terminal(exc: BaseException, fd: int | None = None) -> bool:
|
||||
"""Whether exc is the terminal gone: an OSError, or a termios.error,
|
||||
whose first argument is the errno, answering EIO, EPIPE or ENXIO."""
|
||||
whose first argument is the errno, answering EIO, EPIPE or ENXIO, and,
|
||||
given the terminal's fd, that terminal no longer answering. A failing
|
||||
SD card answers EIO too, and that read error is kept in a crash log."""
|
||||
if isinstance(exc, OSError):
|
||||
return exc.errno in _CLOSED_TERMINAL
|
||||
if type(exc).__name__ == "error" and type(exc).__module__ == "termios":
|
||||
return bool(exc.args) and exc.args[0] in _CLOSED_TERMINAL
|
||||
closed = exc.errno in _CLOSED_TERMINAL
|
||||
elif type(exc).__name__ == "error" and type(exc).__module__ == "termios":
|
||||
closed = bool(exc.args) and exc.args[0] in _CLOSED_TERMINAL
|
||||
else:
|
||||
closed = False
|
||||
return closed and (fd is None or _terminal_gone(fd))
|
||||
|
||||
|
||||
def _terminal_gone(fd: int) -> bool:
|
||||
"""Whether the terminal at fd hung up: a closed window answers EIO to
|
||||
tcgetattr, a live one its settings."""
|
||||
import termios # noqa: PLC0415
|
||||
|
||||
try:
|
||||
termios.tcgetattr(fd)
|
||||
except (termios.error, OSError):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
|
||||
@@ -2557,6 +2557,29 @@ class IdleExit(unittest.TestCase):
|
||||
["RetroBIOS: No button pressed, closing."])
|
||||
|
||||
|
||||
class AReadErrorIsNotAClosedWindow(unittest.TestCase):
|
||||
"""Any EIO read as the window closing: a failing SD card answers EIO
|
||||
too, and that run ended 129, no error.log, no launcher message."""
|
||||
|
||||
def test_eio_counts_only_once_the_terminal_hung_up(self):
|
||||
import pty
|
||||
|
||||
master, slave = pty.openpty()
|
||||
try:
|
||||
card = OSError(errno.EIO, "Input/output error", "/media/card/bios/x.bin")
|
||||
self.assertFalse(install._closed_terminal(card, slave))
|
||||
self.assertFalse(install._closed_terminal(
|
||||
OSError(errno.ENOENT, "No such file"), slave))
|
||||
os.close(master)
|
||||
master = -1
|
||||
self.assertTrue(install._closed_terminal(card, slave))
|
||||
self.assertTrue(install._closed_terminal(termios.error(errno.EIO, "gone"), slave))
|
||||
finally:
|
||||
os.close(slave)
|
||||
if master >= 0:
|
||||
os.close(master)
|
||||
|
||||
|
||||
class AuditRoundFour(unittest.TestCase):
|
||||
"""tui_audit_3.md, each finding held where it was found."""
|
||||
|
||||
|
||||
Reference in new issue
Block a user