Catching both SIGTERM and SIGINT and exiting properly

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?
Take a look at this:

https://linux.die.net/man/2/sigaction
https://en.wikipedia.org/wiki/Unix_signal#SIGINT

and this:

http://www.linuxprogrammingblog.com/code-examples/sigaction

Before you use sa you should intiialze it.

are the following lines correct?
They don't make too much sense. When the program ends it ends. Rasing another signal shouldn't change anything.

Secondly, what if I wanted to simultaneously handle both SIGINT and SIGTERM?
Why would you do so? According to wikipedia they are supposed to mean bascally the same: ending you program. What would you do more?
I have seen those pages, although maybe I don't understand all of their content.

Before you use sa you should intiialze it.


Doesn't the following initialize sa? I've not run into problems with the code I think.

sigaction(SIGINT, &sa, NULL);

Are you referring to the memset line? I will add that if that's the safe and proper thing to have.

They don't make too much sense. When the program ends it ends. Rasing another signal shouldn't change anything


Sorry. I realized that they should be in an if block. What I really meant was:

1
2
3
4
5
if (stopFlag) {
	sa.sa_handler = SIG_DFL; 
	sigaction(SIGINT, &sa, NULL);
	raise(SIGINT);
}


Final edit: so the code works for me now. I think it's handling signals properly, and I can exit if I run the program using SLURM. Also, if the program is run by a shell script, I can Ctrl-C the shell script, interrupt the program, and then the shell script will stop executing.
Last edited on
Topic archived. No new replies allowed.