One of my programs uses ncurses for drawing a small tui. One of my goals is to make it rather portable to other curses implementations. This means that I want to catch a SIGWINCH issued by the terminal emulator on a resize operation myself and update my tui to adhere the changed geometry (and not depend on the resizing facilities of ncurses). Since POSIX (as far as I know) only allows access to sig_atomic_t
variables within the signal handler, I set one to a different state. In the main loop, my program checks whether the state has changed and updates the tui if necessary.
But now, I have the problem that my program hangs in getch
, when an signal arrives. The ncurses documentation states that handled signals never interrupt it. This means the size of the tui is not updated until an input key is pressed.
Is there any portable way to interrupt getch
? My current approach is to ungetch
a dummy key in the signal handler but I'm not sure if this is allowed. Actually I could not find any documentation regarding the fact whether an curses function may be used in a signal handler or not. Any idea how to correctly handle this matter?
Regards
From the FreeBSD documentation getch, interrupt getch depends of the system you are using:
Programmers concerned about portability should be prepared for either of two cases: (a) signal receipt does not interrupt getch; (b) signal receipt interrupts getch and causes it to return ERR with errno set to EINTR. Under the ncurses implementation, handled signals never interrupt getch.
I think you should consider using threads, one thread charged to use getch() and to pass datas to the main thread that treat them. You will be able to kill the thread that uses getch() when the signal SIGWINCH is sent, and to relauch it if you want. But killing the thread that uses getch() maybe useless, because the main thread isn't blocked by getch().
You can get non-blocking inputs without ncurses, as described on this page. But you can use read(STDIN_FILENO, &c, sizeof(char))
to read the input instead of fgetc()
in the example, because read return a value <= 0 if it has failed.