If I run a program in Bash that listens for SIGWINCH, and I resize the terminal that Bash is running in, then the program will receive SIGWINCH. I would like to know how this signal gets relayed to the program running under Bash.
Here is my understanding of what happens, using a sample catch_sig program that I list at the end of this post:
- The terminal emulator will run Bash behind the receiving end of a PTY. Thus, the "STDIN" and "STDOUT" of Bash will be TTYs.
- Bash runs
catch_sigas a sub-process by forking. Thecatch_sigprocess inherits Bash's FDs for I/O, which are the TTYs mentioned above. - When the size of the terminal emulator changes it should call
ioctl(pty_fd, TIOCSWINSZ, &size), wherepty_fdis the sending end of the above PTY. This call toioctlwill update the size of the receiving TTY and will attempt to sendSIGWINCHthe process group for the TTY. - Bash and
catch_sigare part of the above process group, soSIGWINCHgets sent to both of them individually.
One difficulty I'm having with the above however, is that if I attempt to send SIGWINCH to the process group for Bash manually with kill then catch_sig doesn't receive the signal. For example, if the PID (and process group) for Bash is 123 and I run catch_sig in it, and then I run kill -WINCH -123 in a separate pane, then catch_sig doesn't receive the signal. Why is this this the case?
The following is source code for a demonstrative catch_sig program, as mentioned above:
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
static void sigwinch_handler(int sig) {
printf("got signal: %d\n", sig);
}
int main() {
signal(SIGWINCH, sigwinch_handler);
printf("waiting for signal...\n");
pause();
return 0;
}