Search code examples
csignalsncurseswindow-resize

After intercepting SIGWINCH in a ncurses-based program, key presses are not recognized


I have a small ncurses-based program which performs basic chemical calculations. Its main function is like this:

int main() {   
  initscr();   
  cbreak();   
  nonl();   
  noecho(); 
  /* draws borderlines from position 0 to (COLS - 1) 
     for purely decorative purposes at the top and bottom
     of the screen */
  draw_GUI(); 
  keypress_loop();   
  endwin(); 
};

The keypress_loop() function waits for user to press a key and then prints the key's symbol on the screen if the key is letter or digit and makes a beep if the key is neither letter nor digit. If user presses F2 the function returns and the program ends.

void  keypress_loop() 
{
   int key;
   while ((key = wgetch(stdscr)) != KEY_F(2))
      process_key(key); 
}

So far everything works as intended. But then I add a signal handler for SIGWINCH to make sure that borderlines are redrawn correctly after resizing the terminal emulator's window. Before initscr() in the main() function I insert:

signal(SIGWINCH, handle_resizing);

And handle_resizing() looks like this:

static void
handle_resizing(int signo) {
      endwin();
      initscr();   
      cbreak();   
      nonl();   
      noecho();
      draw_GUI();
}

This SIGWINCH-handling function redraws the borderlines as intended. But the problem is that, when user presses a key after resizing, the program ignores this key. And only after user presses a key three or more times the program starts recognizing the key and then everything works OK! How can I make the program to immediately recognize key presses after resizing?


Solution

  • The handle_resizing function calls functions which are unsafe to use in a signal handler. The resizeterm manual page has a section discussing this. Your program should use the KEY_RESIZE return value from getch.