From 623c4914d1d7c8e8bd9f3d1bf41fcc930d94499d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C5=99emysl=20Janouch?= Date: Sun, 19 Apr 2020 22:40:57 +0200 Subject: [PATCH] Work around an infinite loop issue --- sdn.cpp | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/sdn.cpp b/sdn.cpp index 9734a80..13bca54 100644 --- a/sdn.cpp +++ b/sdn.cpp @@ -41,6 +41,7 @@ #include #include #include +#include #include #include @@ -1126,6 +1127,9 @@ fun handle_editor (wint_t c) { } fun handle (wint_t c) -> bool { + if (c == WEOF) + return false; + // If an editor is active, let it handle the key instead and eat it if (g.editor) { handle_editor (c); @@ -1369,10 +1373,27 @@ fun load_colors () { } } +fun monotonic_ts_ms () -> int64_t { + timespec ts{1, 0}; // A very specific fail-safe value + (void) clock_gettime (CLOCK_MONOTONIC, &ts); + return ts.tv_sec * 1e3 + ts.tv_nsec / 1e6; +} + fun read_key (wint_t &c) -> bool { + // XXX: on at least some systems, when run over ssh in a bind handler, + // after closing the terminal emulator we receive no fatal signal but our + // parent shell gets reparented under init and our stdin gets closed, + // so we'd keep getting ERR in an infinite loop, as that is what ncurses + // automatically converts EOF into. The most reasonable way to detect this + // situation appears to be via timing. Checking errno doesn't work and + // resetting signal dispositions or the signal mask has no effect. + auto start = monotonic_ts_ms (); int res = get_wch (&c); - if (res == ERR) - return false; + if (res == ERR) { + c = WEOF; + if (monotonic_ts_ms () - start >= 50) + return false; + } wint_t metafied{}; if (c == 27 && (res = get_wch (&metafied)) != ERR)