0

Just for fun I'm trying to write a library that does everything ncurses does, using iostreams and sending escape sequences directly to the terminal.

I'm trying to handle SIGWINCH to tell the library when the terminal is resized. The program responds normally until I resize the terminal, then it stops responding to input, even CTRL-C (although I'm not handling SIGINT, and have the terminal in "raw" mode using termios).

Here's some code snippets I've copied out of my code to show how I've set up the signal handler.

void handle_sigwinch(int sig)                                   
{                                                                               
  if(sig == SIGWINCH)    
  {
    // set a flag here
  }
}
void setup_signals()                                            
{       
  struct sigaction new_sig_action;                                            
  new_sig_action.sa_handler = handle_sigwinch;                
  sigemptyset (&new_sig_action.sa_mask);                                      
  new_sig_action.sa_flags = 0;                                                
  sigaction (SIGWINCH, NULL, &old_sig_action_);                               
  if (old_sig_action_.sa_handler != SIG_IGN)                                  
  {                                                                           
    sigaction (SIGWINCH, &new_sig_action, NULL);                              
  }                                                                           
}

int main()
{
  setup_signals();
  int ch;
  // exit if ctrl-c is pressed
  while((ch == cin.get()) != 3)
  {
     if(ch > 0)
       cout << (char)ch;
  }
}

I've tailored my code according to the example provided at https://www.gnu.org/software/libc/manual/html_node/Sigaction-Function-Example.html#Sigaction-Function-Example for setting up the signal handler.

Is there something I've failed to do after handling SIGWINCH that is causing my program to stop working?

Edit: I left out the code where I set up the terminal using cfmakeraw and tcsetattr, and prior to this I sent an escape sequence for putting xterm into the alternate screenbuffer mode.

R. A.
  • 1
  • 1
  • 2
  • Does this code actually match what you are testing; specifically, have you tested not doing anything in the SIGWINCH handler as shown in the snippets above? – madscientist159 Jul 29 '17 at 07:51
  • The code here seems fine. Please show all the actual code you have inside your signal handler, it can be quite important. You would probably also get quite far in figuring out the problem if you attach a debugger when your program appears to hang, so you can see what the code is doing. – nos Jul 29 '17 at 07:51
  • @madscientist159 actually, that's all the handler does. It checks the signal and does nothing. I had some code in there, but once I noticed the hang-ups I yanked it out to see if that was causing the issue. It still hangs. – R. A. Jul 29 '17 at 15:32
  • @nos I don't know why I didn't do that; it was getting pretty late when I posted. I just ran the debugger, and I get the same behavior but I can see the program isn't actually "hanging", it just isn't receiving the input. Something about the signal handler must have either broken standard input (which I doubt) or the `cin` stream object. – R. A. Jul 29 '17 at 15:36
  • @nos As a result of following your suggestion I found a better way of phrasing my google search to "input stream broken after signal handler" and found the correct answer on Stackoverflow. Thanks! Is there some way I can send rep your way? – R. A. Jul 29 '17 at 15:44

1 Answers1

0

Thanks to nos's comment, I found through the debugger that the program was running normally, but cin.get() wasn't receiving valid input anymore. So I changed my google search from "program hangs after signal handler" to "input stream broken after signal handler" and found this answer on StackOverflow, which allowed me to realize that the input stream was in an error state after the signal handler was called.

I had placed a check before the input to ignore a character value of -1 (I must have been thinking of the Arduino library read statement when I did that, where -1 is an indicator that no input is available). So the program was basically ignoring errors on the input stream. (I edited my question's code to reflect that omission).

I placed a cin.clear() statement immediately before the read in the loop, and now the program works as expected.

R. A.
  • 1
  • 1
  • 2