I've blocked, and then waited for a signal via the following code:
sigset_t set;
sigfillset(&set); // all signals
sigprocmask(SIG_SETMASK, &set, NULL); // block all signals
siginfo_t info;
int signum = sigwaitinfo(&set, &info); // wait for next signal
struct sigaction act;
sigaction(signum, NULL, &act); // get the current handler for the signal
act.sa_handler(signum); // invoke it
The last line generates a segmentation fault, as the handler is set to SIG_DFL
(defined as 0
). How can I manually invoke the default handler if it's set to SIG_DFL
or SIG_IGN
? Also note that SIG_IGN
is defined as 1
.
I'm not aware of the way to do it.
Only suggestion I have is to look into the
man 7 signal
and perform manually the action according the table you see there.Ign
is nothing.Core
is call toabort()
.Term
is_exit()
.Of course you can also set signal handler back to SIG_DFL and then
kill(getpid(),THE_SIG)
(or its equivalentraise(THE_SIG)
). (I personally do not likeraise
because on some systems it might produce some messages on stderr.)As you discovered you cannot invoke SIG_DFL and SIG_IGN per se. However, you can more-or-less mimic their behavior.
Briefly, imitating normal signal disposition would be:
sa_handler
sDoes this do what you want?
UPDATE (in response to OP's excellent questions)
Yes. Something like:
It's slightly more efficient to noop in userspace than by three syscalls (re-raise, unmask, re-mask). Moreover, CHLD has special semantics when SIG_IGNored.
Originally (check answer edits) I didn't -- re-raised it in the SIG_IGN case, because IGNored CHLD signals tell the kernel to automatically reap children.
However, I changed it because "natural" CHLD signals carry information about the terminated process (at least PID, status, and real UID). User-generated CHLD signals don't carry the same semantics, and, in my testing, IGNoring them doesn't cause 2.6 to autoreap queued zombies whose SIGCHLD was "missed." So, I do it myself.
If we're stopped (not executing) and CONT is blocked, we will never receive the signal to wake us up!
Personal preference;
raise()
would work, too.I see 2 mistakes in your code :
1) You should reverse the last two lines like this :
2) You must pass a function handler to the fiedl sa_handler instead of a int. The prototype of the function shoudl look like this :
If you want the default handler to be invoked, you should set the field sa_handler to SIG_DFL and it should work.