Handle reading from stdin returning 0

0 means stdin was closed, this is quite unexpected as we would usually
get a SIGHUP, but it looks like in some rare case this happens and
it leads to an infinite loop trying to handle stdin events (as it
will always be readable from now on).

Fixes #3557
This commit is contained in:
Maxime Coste 2020-11-02 22:52:59 +11:00
parent 42301f32ca
commit 94ac3084e1

View File

@ -316,7 +316,7 @@ bool NCursesUI::Palette::set_change_colors(bool change_colors)
} }
static sig_atomic_t resize_pending = 0; static sig_atomic_t resize_pending = 0;
static sig_atomic_t sighup_raised = 0; static sig_atomic_t stdin_closed = 0;
template<sig_atomic_t* signal_flag> template<sig_atomic_t* signal_flag>
static void signal_handler(int) static void signal_handler(int)
@ -351,7 +351,7 @@ NCursesUI::NCursesUI()
enable_mouse(true); enable_mouse(true);
set_signal_handler(SIGWINCH, &signal_handler<&resize_pending>); set_signal_handler(SIGWINCH, &signal_handler<&resize_pending>);
set_signal_handler(SIGHUP, &signal_handler<&sighup_raised>); set_signal_handler(SIGHUP, &signal_handler<&stdin_closed>);
set_signal_handler(SIGTSTP, [](int){ NCursesUI::instance().suspend(); }); set_signal_handler(SIGTSTP, [](int){ NCursesUI::instance().suspend(); });
check_resize(true); check_resize(true);
@ -577,7 +577,7 @@ void NCursesUI::check_resize(bool force)
Optional<Key> NCursesUI::get_next_key() Optional<Key> NCursesUI::get_next_key()
{ {
if (sighup_raised) if (stdin_closed)
{ {
set_signal_handler(SIGWINCH, SIG_DFL); set_signal_handler(SIGWINCH, SIG_DFL);
set_signal_handler(SIGHUP, SIG_DFL); set_signal_handler(SIGHUP, SIG_DFL);
@ -596,9 +596,13 @@ Optional<Key> NCursesUI::get_next_key()
} }
static auto get_char = []() -> Optional<unsigned char> { static auto get_char = []() -> Optional<unsigned char> {
unsigned char c = 0; if (not fd_readable(STDIN_FILENO))
if (fd_readable(STDIN_FILENO) and read(STDIN_FILENO, &c, 1) == 1) return {};
if (unsigned char c = 0; read(STDIN_FILENO, &c, 1) == 1)
return c; return c;
stdin_closed = 1;
return {}; return {};
}; };