In Android the bionic loader sets a default signal handler for every process on statrtup:
void debugger_init()
{
struct sigaction act;
memset(&act, 0, sizeof(act));
act.sa_sigaction = debugger_signal_handler;
act.sa_flags = SA_RESTART | SA_SIGINFO;
sigemptyset(&act.sa_mask);
sigaction(SIGILL, &act, NULL);
sigaction(SIGABRT, &act, NULL);
sigaction(SIGBUS, &act, NULL);
sigaction(SIGFPE, &act, NULL);
sigaction(SIGSEGV, &act, NULL);
sigaction(SIGSTKFLT, &act, NULL);
sigaction(SIGPIPE, &act, NULL);
}
I would like to set it back to its default, meaning I want to ignore these signal and that the default handler will take place (CORE DUMP)
How do I revert the action performed ? I want to ignore all these as if the above function never was called
Read signal(7), sigaction(2) and perhaps signal(2).
You could call
signal(SIGILL, SIG_DFL);
signal(SIGABRT, SIG_DFL);
and so on early in your main (which is entered after dynamic loading)
You could also use sigaction with sa_handler set to SIG_DFL
Of course, things are more tricky if you want to default handle these signals before your main, e.g. in some static constructor!
I found it could lead unexpected behavior when mixed using sigaction and signal to set for one process.
From signal(2) posted above(wouldn't surprise me if this warning wasn't there 8 years ago):
WARNING: the behavior of signal() varies across UNIX versions,
and has also varied historically across different versions of
Linux. Avoid its use: use sigaction(2) instead.
Looking at https://docs.oracle.com/cd/E19455-01/806-5257/tlib-49639/index.html
int pthread_sigmask(int how, const sigset_t *new, sigset_t *old);
When the value of new is NULL, the value of how is not significant and the signal mask of the thread is unchanged. So, to inquire about currently blocked signals, assign a NULL value to the new argument.
So I guess you could use that to get the current sigmask and just wipe each one
sigset_t tempSet;
pthread_sigmask(SIG_SETMASK, NULL, &tempSet);
sigdelset(&tempSet, /*Signal you don't want to handle*/);
sigdelset(&tempSet, /*repeat for each signal*/);
pthread_sigmask(SIG_SETMASK, &tempSet, NULL);
It's pretty much the same thing with sigact to query the current action for a signal, from sigaction(2)
sigaction() can be called with a NULL second argument to query
the current signal handler.
It's not clear to me the ramifications of, in my case, having SIGKILL in the first call to sigaction
struct sigaction sigAct;
sigaction(SIGKILL, NULL, &sigAct);
sigAct.sa_handler = SIG_DFL; // Ensure default handling of Kill signal
sigaction(/*Signal you don't want to handle*/, &sigAct, NULL);
sigaction(/*repeat for each signal*/, &sigAct, NULL);
Using siggetmask is obsolete by sigprocmask, and sigprocmask is only for single threaded environments.
Related
I tried to find an answer to my question at this post: Signal handler and waitpid coexisting but for me isn't very clear at the moment.
I try to explain my problems:
I'm trying to write a C program that concerns IPC between a parent process and its children.
The parent process creates N child processes, then it waits for the termination in a loop like this:
while((pid_term = waitpid(-1, &status, 0)) != -1)
After X seconds, parent receives SIGALRM, then with the sigaction system call,
it catches the alarm:
struct sigaction act;
act.sa_handler = alarmHandler;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
sigaction(SIGALRM, &act, NULL);
But, when the handler function returns, the waitpid also returns -1, and the parent process exits from the while loop above.
At the moment, the handler function has an empty body.
I ask myself what happened — why did waitpid() return -1 after the handler invocation even though most of the children are still alive? Why doesn't this happen with signal() function?
The default behavior of signal handlers established by sigaction is to interrupt blocking system calls; if you check errno after the alarm fires you should observe it to be set to EINTR. This behavior is almost never what you want; it's only the default for backward compatibility's sake. You can make it not do this by setting the SA_RESTART bit in sa_flags:
struct sigaction act;
act.sa_flags = SA_RESTART;
act.sa_handler = alarmHandler;
sigemptyset(&act.sa_mask);
sigaction(SIGALRM, &act, 0);
One of the most important reasons to use sigaction instead of signal, is that when you use signal it is unpredictable whether or not the signal handler will interrupt blocking system calls. (The System V lineage picked one semantic and the BSD lineage picked the other.)
I'm supposed to install a signal handler to call the function stopContinue() when I receive SIGINT. Here is my code snippet in C, but I'm not sure if this correct. Please let me know where I'm going wrong.
struct sigaction act;
memset(&act, '\0', sizeof(act));
action.sa_flags = 0;
action.sa_handler = stopContinue;
sigaction(SIGINT, &act, NULL);
Does this look roughly correct?
There is a discussion on using sigaction vs. action, and the use of flags here that is different than another question, this is not a dupe.
Why use sigaction if you're not even going to use the struct's sa_flags member? To call stopContinue when Ctrl+C is pressed, you can use:
signal(SIGINT, stopContinue);
If you simply want to ignore Ctrl+C, you can make it even easier:
signal(SIGINT, SIG_IGN);
SIG_IGN is a macro to ignore signals.
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);
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.
I have set a handler for each signal (SIGCHLD, SIGTSTP, SIGINT), now I need to block other signals while some handler running .
There is some resources like sigaction(2) and Blocking for Handler , but I didn't understand what should I do in my situation or how to use the code .
little information :
handlers : sigchldHandler, sigintHandler, sigtstpHander => signals.c
there is a file called smash.c which contains an infinite loop to get commands all the time .
thanks in advance
When setting up the sigaction, you can specify a mask of signals that should be blocked when the handler is running.
You use it like so:
struct sigaction act;
sigset_t set;
memset(&act,0,sizeof act);
sigemptyset(&set);
sigaddset(&set, SIGUSR1);
sigaddset(&set, SIGSTP);
act.sa_mask = set;
act.sa_handler = sigchldHandler;
act.sa_flags = SA_RESTART;
sigaction(SIGCHLD, &act, NULL);
This will block SIGUSR1 and SIGSTP while your handler for SIGCHLD is running. Do the same for your 2 other handlers as well.
I have sigaction defined and it works fine. However I want to restore the original signal after my action is completed. This is my sigaction:
static void signal_handler(int signal, siginfo_t *info, void *reserved)
{
//Some logging statements
//How do I restore the original signal here??
}
The signal handler is set from JNI_Onload:
extern "C" jint JNI_OnLoad(JavaVM* vm, void* /*reserved*/)
{
struct sigaction handler, action_old;
memset(&handler, 0, sizeof(handler));
handler.sa_sigaction = signal_handler;
handler.sa_flags = SA_SIGINFO;
sigaction(SIGILL, &handler, &action_old);
sigaction(SIGABRT, &handler, &action_old);
sigaction(SIGBUS, &handler, &action_old);
sigaction(SIGFPE, &handler, &action_old);
sigaction(SIGSEGV, &handler, &action_old);
sigaction(SIGSTKFLT, &handler, &action_old);
//Can I restore prior signal here???
return JNI_VERSION_1_6;
}
Save the old actions in global (or file-scope) variables (or an array indexed by signal id) and call sigaction from inside your signal handler to restore the previous behavior. sigaction is guaranteed to be async-signal safe.
See also: http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_04_03
http://www.gnu.org/s/hello/manual/libc/Basic-Signal-Handling.html - says:
The signal function returns the action that was previously in effect for the specified signum. You can save this value and restore it later by calling signal again.