1

Can anyone help me to understand what are the differences between the following three ways of handling a signal? I'm operating in a client/server in C.

Edit: I've understood that the 1st example is wrong, now I'd like to know which is better/possible, the 2nd one ore the third one? I've also read around the web that someone does a mix between them, using the "struct sigaction sig" in "sigemptyset" and "sigaddset", without any sigprocmask. Is this better than both my solutions?

Handler:

void closeSig(){
    close(socketAccept);
    close(socket);
    exit(1);
}

1st example:

signal(SIGINT, closeSig);

2nd example:

sigset_t set;
struct sigaction sig;
sigemptyset(&set);
sigaddset(&set, SIGINT);
sig.sa_sigaction = &closeSig;
sig.sa_flags = SA_SIGINFO;
sig.sa_mask = set;
sigaction(SIGINT, &sig, NULL);
sigprocmask(SIG_UNBLOCK, &set, NULL);

3rd example:

struct sigaction sig;
sig.sa_sigaction = &closeSig;
sig.sa_flags = SA_SIGINFO;
sigaction(SIGINT, &sig, NULL);
testermaster
  • 1,031
  • 6
  • 21
  • 40
  • 2
    Did you search before asking? Did you look at [What is the difference between `sigaction()` and `signal()`?](http://stackoverflow.com/questions/231912/what-is-the-difference-between-sigaction-and-signal/232711#232711) What information was missing for you? Why didn't you mention that you'd looked at it? – Jonathan Leffler Oct 31 '14 at 05:05
  • @JonathanLeffler Yes I'm sorry it was a typo. I've searched but I didn't find your post, which is really clear about the differnces between sigaction() and signal(). But there's still a case: the differences between using sigaction with a sigset+sig_unblock or without sigset? :/ – testermaster Oct 31 '14 at 05:14
  • 1
    You show [`sigprocmask()`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigprocmask.html) in the question, but mention [`sigset()`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigset.html) and its relatives (`sigrelse()`, `sighold()`, `sigpause()`, `sigignore()`) in your comment. There's also [`pthread_sigmask()`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_sigmask.html). The `sigset()` family should not be used, in general — they are marked 'obsolescent' and new code should not use them. What are you really interested in? – Jonathan Leffler Oct 31 '14 at 07:00
  • I feel calling `exit()` from a signal handler is not good idea. – alk Oct 31 '14 at 18:01
  • @JonathanLeffler I'm studying at the university, and I'm requested to create a server/client and handle the signals, for learning purposes, that's why I'd like to understand the differences between the second example and the 3rd one. Ragarding the results I'll get, it'll be the same if I use the second example or the 3rd one? – testermaster Nov 01 '14 at 02:58
  • @JonathanLeffler I've read many sources right now, but still can't figure out which is the correct solution. :( – testermaster Nov 03 '14 at 02:27

1 Answers1

2

According to POSIX sigaction(), the function closeSig() is not strictly a suitable callback for signals. It should be:

void closeSig(int signum);

for a regular callback, but as you're using SA_SIGINFO, it needs to be:

void closeSig(int signum, siginfo_t *info, void *context);

You also need to look at the POSIX specification for sigprocmask().

Let's look at the second example:

sigset_t set;
struct sigaction sig;
sigemptyset(&set);
sigaddset(&set, SIGINT);
sig.sa_sigaction = &closeSig;
sig.sa_flags = SA_SIGINFO;
sig.sa_mask = set;
sigaction(SIGINT, &sig, NULL);
sigprocmask(SIG_UNBLOCK, &set, NULL);

The & on &closeSig is unnecessary, but harmless. However, the type of closeSig() shown in the question is wrong. The sigset_t says that SIGINT (only) will be blocked when the interrupt handler is called, but that would happen anyway since the flags don't include SA_NODEFER. So, the code handling set is superfluous to sigaction().

The call to sigprocmask() unblocks interrupts (SIGINT). It is not clear why this is called; there would have to be some previous call to sigprocmask() that blocked interrupts for it to make a difference. However, after this, if an interrupt is sent to the process, the closeSig() function will be called with arguments that it does not expect.

The third example is:

struct sigaction sig;
sig.sa_sigaction = &closeSig;
sig.sa_flags = SA_SIGINFO;
sigaction(SIGINT, &sig, NULL);

This is fairly close to the minimal operations described in dissecting and simplifying the second example. The main problem is that sig.sa_mask is set to an indeterminate value. The code should be:

struct sigaction sig;
sig.sa_sigaction = &closeSig;
sig.sa_flags = SA_SIGINFO;
sigemptyset(&sig.sa_mask);
sigaction(SIGINT, &sig, NULL);

This is now equivalent to the second example.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • Thanks for your patience, now things are a bit more clear. Now, let's assume that I've to handle also other signals, like SIGALARM. After sigalarm is handled, it re-enables "sigaction(SIGALARM, &signAlarm, NULL);" and then returns the control to a function "fun()". If we look at the 2nd example, with sigset_t set and we put the sigprocmask unblock at the beginning of fun(), it has sense because this enables all signals to be handled again,right? In this case,sigset_t can be considered useful, cause I can add into it all the signals I want and unblock them all with the sigprocmask call,right? – testermaster Nov 03 '14 at 05:28
  • When I wrote "it re-enebles", I meant that in the handler i put that code, and then "fun();". Thanks once again! – testermaster Nov 03 '14 at 05:45