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)