Hello, comment in curses.c says: * The observed behavior, however, is different: wgetch() consistently * returns ERR with EINTR when a signal is handled by the shell "trap" * command mechanism. Further, it consistently returns ERR twice, the * second time without even attempting to repeat the interrupted read, * which has the side-effect of NOT updating errno. A third call will * then begin reading again. * * Therefore, to properly implement signal trapping, we must (1) call * wgetch() in a loop as long as errno remains EINTR, and (2) clear * errno only before beginning the loop, not on every pass. Logic: 1. The comment assumes EINTR being not reset by curses implies the read will be "mock". It could assume that first read after EINTR will be mock based on evidence, but it quietly assumes this for all subsequent reads. - hidden assumption: errno is needed by curses to track its state after interrupt (!). 2. The comment fits getch-like-calls without timeout. The loop: while ((ret = wget_wch(w->win, &wi)) == ERR) { if (errno != EINTR || errflag || retflag || breaks || exit_pending) break; } will nicely detect EINTR after ERR return value, then go inside wget_ch() again indefinitely long, then receive ~ERR and jump over errno == EINTR. It also will skip the "mock" read that author probably spotted. -> conclusion: author designed the loop only for no-timeout-reads 3. Timeouts: -> OS X, Linux man wget_wch: "In no-delay mode, if no input is waiting, the value ERR is returned.", -> OS X, Linux man wtimeout: "The timeout and wtimeout routines set blocking or non-blocking read for a given window. (...) If delay is positive, then read blocks for delay milliseconds, and returns ERR if there is still no input." So, clash happens – errno is not reset (see below), ERR is returned after timeout, and loop hangs. 4. Ncurses can reset or not errno. We should now note: it is the possibility-of-no-reset that matters. Not possible-reset. If there is any curses library that doesn't reset errno, then the loop is wrong. Proof for ncurses 5.4 (browse for "errno"): https://github.com/psprint/zsh-tools-private/blob/master/data/lib_getch.c 5. Library-not-resetting-errno is the standard: https://www.securecoding.cert.org/confluence/pages/viewpage.action?pageId=6619179 The patch resets errno after ERR/EINTR. Removed also most of the long comment. It was hard to find solution because of that comment, it was making impression of some inherent drastic problems with diverse curses implementations, while there are none, the Linux, FreeBSD documentation just says about getch being either interrupted or not, THAT'S ALL. No internet page exists that mentions any problems here. -- Sebastian Gniazdowski psprint3@fastmail.com