SIGWINCH and cout acting unreliably

47 Views Asked by At

I am trying to write a simple text editor in C++.

One of the features that I am trying to implement is dynamic resizing of the text when the window size changes. To do this, I am using a signal handler for SIGWINCH with sigaction which updates the number of rows and columns of a global config object as follows

void registerHandler() {
  struct sigaction resize;
  memset(&resize, '\0', sizeof(resize));
  resize.sa_handler = handleWINCH;
  sigaction(SIGWINCH, &resize, NULL);
}

void getTerminalSize() {
  winsize w;
  ioctl(STDIN_FILENO, TIOCGWINSZ, &w);
  config.nCols = w.ws_col;
  config.nRows = w.ws_row;
}

void handleWINCH(int) {
  getTerminalSize();
  draw();
}

Right now, I am just displaying the number of columns stored in a global config object using the draw method, as such

void draw() {
  std::cout << ERASESCREEN << HOME << std::flush;
  std::cout << config.nRows;
}

The problem is that this code acts very unreliably. Sometimes it works and sometimes it crashes prematurely and outputs a "%" character for seemingly no reason.

The terminal is in raw mode, enabled with cfmakeraw

void enableRawMode() {
  tcgetattr(STDIN_FILENO, &config.initalConfig);
  atexit(disableRawMode);

  termios raw = config.initalConfig;
  cfmakeraw(&raw);

  tcsetattr(STDERR_FILENO, TCSAFLUSH, &raw);
}

HOME and ERASESCREEN are ANSI escape sequences to reset the cursor and clear the screen, defined as follows

#define ERASESCREEN "\x1b[2J"
#define HOME "\x1b[H"

Lastly, I enabled the std::unitbuf to hopefully mitigate any issues caused from the output buffering of cout.

  std::cout << std::unitbuf << HOME << ERASESCREEN <<std::flush;

Furthermore, I've noticed that this issue with outputting and signal handling only happens in raw mode. Otherwise, the program seems to respond to the WINCH signal normally. I suspect there might be an issue with the output stream, which is why I keep trying to flush manually, but I don't know C++ and UNIX programming well enough to be able to guess any further.

I've uploaded the full code as well in case I did not include something important.

Thanks in advance!

0

There are 0 best solutions below