On Sat, Mar 28, 2026 at 07:24:44AM +0100, Klaas van Aarsen wrote: > Thanks for your timely responses. > > However, it seems we cannot use errno after getch() returns ERR. In our > testing, when a SIGHUP occurs, the underlying read() call simply returns 0 > (EOF) rather than a system error. > Since ncurses appears to map both EOF and a halfdelay timeout to the same > ERR value without setting errno, we lose the ability to distinguish between > 'no input' and 'terminal gone.' > > We could use napms() to throttle the CPU, but that leaves the process alive > in a 'zombie' state until a user manually kills it. > We really want to detect the disconnection and terminate gracefully. > > It looks as if we are forced to set a global volatile sig_atomic_t flag on > SIGHUP and check it manually every time getch() returns ERR.
If fileno(stdin) is actually closed, the read should set errno to EBADF (9). You could close it in a signal handler for SIGHUP (that's safe), and check error on ERR return from wgetch. I seem to recall some discussion many years ago (e.g., ~20) where the terminal was defunct, but didn't actually close the input -- I think the responsibility for that should be in the calling application since _it_ has to know what's a graceful way to shut down. But if you're already getting ERR from wgetch (as indicated in the initial report), I don't see what state stdin might be in if there's no errno set. > Does ncurses provide any internal mechanism to distinguish an EOF from a > timeout, or is the signal-flag approach the standard way to handle this in > a curses application? > > > > On Sat, Mar 28, 2026 at 12:30 AM G. Branden Robinson < > [email protected]> wrote: > > > At 2026-03-27T18:23:57-0400, Thomas Dickey wrote: > > > On Fri, Mar 27, 2026 at 06:40:42PM +0100, Klaas van Aarsen wrote: > > > > We have a bug in the Angband code related to getch of ncurses ( > > > > https://github.com/angband/angband/pull/6559). > > > > It turns out that getch returns ERR when the terminal connection is > > > > broken (SIGHUP). The code currently interprets it as a timeout (set > > > > by halfdelay) and spins on input, leaving a zombie process with 100% > > > > CPU. The man page on getch only mentions that errno might be EINTR > > > > if the getch call is interrupted, but nothing on a broken terminal > > > > connection. How might we detect that the terminal connection is > > > > broken? > > [...] > > > ...mixing getch with fgets doesn't appear to be a good idea, since > > > ncurses doesn't use the input stream -- only the file descriptor. > > > Expect some difference in behavior. > > > > The ncurses man pages explain this, too. > > > > ncurses(3NCURSES): > > > > ENVIRONMENT > > ... > > NCURSES_NO_SETBUF > > (Obsolete) Prior to internal changes developed in ncurses 5.9 > > (patches 20120825 through 20130126), the library used setbuf(3) to > > enable fully buffered output when initializing the terminal. This > > was done, as in SVr4 curses, to increase performance. For testing > > purposes, both of ncurses and of certain applications, this feature > > was made optional. Setting this variable disabled output > > buffering, leaving the output stream in the original (usually line‐ > > buffered) mode. > > > > Nowadays, ncurses performs its own buffering and does not require > > this workaround; it does not modify the buffering of the standard > > output stream. This approach makes the library’s handling of > > keyboard‐initiated signals more robust. A drawback is that certain > > unconventional programs mixed stdio(3) calls with ncurses calls and > > (usually) got the behavior they expected. This is no longer the > > case; ncurses does not write to the standard output file descriptor > > through a stdio‐buffered stream. > > > > As a special case, low‐level API calls such as putp(3NCURSES) still > > use the standard output stream. High‐level curses calls such as > > printw(3NCURSES) do not. > > > > Regards, > > Branden > > -- Thomas E. Dickey <[email protected]> https://invisible-island.net
signature.asc
Description: PGP signature
