I am learning to use
sigaction
to catch signals, and I have a few confusions to free up. I read that the suggested way of setting up a program to catch SIGINT is like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
|
#include <iostream>
#include <csignal>
#include <unistd.h>
volatile sig_atomic_t stopFlag = 0;
static void handler(int signum) {
stopFlag = signum;
}
int main() {
struct sigaction sa;
sa.sa_handler = handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART; /* Restart functions if
interrupted by handler */
sigaction(SIGINT, &sa, NULL);
while (true) {
std::cout << "in loop\n";
sleep(1);
if (stopFlag)
break;
}
std::cout << "exiting" << std::endl;
// reset handler to default and exit by SIGINT
// are the following lines correct?
sa.sa_handler = SIG_DFL;
sigaction(SIGINT, &sa, NULL);
raise(SIGINT);
}
|
Please let me know if this is correct, particularly the first few lines.
According
https://www.cons.org/cracauer/sigint.html, shells like Bash are WCE (Wait and cooperative exit). That is, if you are running shell script that is running a program, and you send a Ctrl-C signal, and the program has a handler for SIGINT, the shell will wait to see if the program exits by SIGINT to cancel the shell script. So I wanted to check that the last lines of my program are correct in the way I am exiting the program upon SIGINT. The link has an example for
signal
, but I read it's better to use
sigaction
, which I am using here. I read that sigaction doesn't need to be reset, but being a novice, I don't quite understand the full meaning of the word "reset." So I am most unsure about the last three lines of my program.
Secondly, what if I wanted to simultaneously handle both SIGINT and SIGTERM?
I tried adding
sigaction(SIGTERM, &sa, NULL);
right after the first sigaction call. This seemingly let me end my program by both Ctrl-C and the bash kill command. But in both cases, I am exiting the program by raising SIGINT. Does that matter? In particular, the integer value of stopFlag is 1 in both the case of SIGINT and SIGTERM, so I am not sure if I can use a switch statement to distinguish between the two.
Thirdly, and perhaps more obscurely, the code I am writing will eventually run on a cluster managed by SLURM. According to SLURM documentation,
scancel
sends SIGTERM. But in my test by using the above program, I am seemingly unable to
scancel
my program. The loop just continues running. Is there something particular that I need to do for SLURM?