First of all, I do know that there was a similar question here in the past.
But that question wasn't answered properly. Instead, it diverted into suggestion what to do to catch signals.
So just to clarify: I've done whatever needs to be done to handle signals.
I have an application that forks a daemon that monitors the main process through pipe.
If a main process crashes (e.g. segmentation fault), it has a signal handler that writes all the required info to pipe and aborts.
The goal is to have as much info as possible when something bad happens to the application, w/o messing with "normal" operation, such as SIGHUP, SIGUSR1, etc.
So my question is: which signals should I catch?
I mean signals that w/o me catching them would cause application to abort anyway.
So far I've come up with the following list:
SIGINT (^C, user-initiated, but still good to know)
SIGTERM (kill <pid> from shell or, AFAIK, can be result of OutOfMemory)
SIGSEGV
SIGILL
SIGFPE
SIGBUS
SIGQUIT
Does anybody know if I miss something? kill -l has lots of them... :)
I'm looking at my copy of advanced programming the unix environment (Stevens). According to the table in the section on signals, the following POSIX signals will by default terminate the process, if you don't catch them. It wouldn't be unreasonable to monitor all of these that you don't use:
SIGABRT
SIGALRM
SIGFPE
SIGHUP
SIGILL
SIGINT
SIGKILL
SIGPIPE
SIGQUIT
SIGSEGV
SIGTERM
SIGUSR1
SIGUSR2
You can catch all of these except SIGKILL, but hopefully SIGKILL won't come up very often for you.
Note that your signal man page (man 7 signal) should give you the proper list for your system - this is the POSIX list, and may differ depending on your architecture.
You should not catch the signal and write the code to a pipe. This is both unnecessary and not failsafe.
Let me quote an answer from the question you linked to, to point out why it's not failsafe: "What makes you think that a SEGV hasn't already corrupted your program memory"
Now you may be wondering how to do it better, and why I've said it is "unnecessary".
The return code of the waitpid syscall can be checked using WIFSIGNALED() to determine whether the process was terminated normally or via a signal, and WTERMSIG() will return the signal number.
This is failsafe and it does not require a handler or a pipe. Plus, you don't need to worry what to catch, because it will report every signal that terminates your process.
It depends: whatever signal you like if that's useful to inform the user something bad just happened. However SIGKILL and SIGSTOP cannot be caught.
Related
I want to create an Units test framwork, but to provide a good reporting I need to catch SIGABRT, SIGSEGV and probably others signals to prevent my process from being killed (And so, to be able to continue the tests processing)...
But I don't know how to do this and so, I need information:
SIGABRT is a thread direct signal ?
What happens if I only use the main thread to catch the SIGABRT (or SIGSEGV) signal? Could the thread that called abort return from its call (I hope not) ?
If you have any useful documents, links or tutorial, I'm interested. It's for a C code using pthreads.
Thanks for your help
I need to catch SIGABRT, SIGSEGV and probably others signals to prevent my process from being killed
This is an exercise in futility. After SIGABRT or SIGSEGV is raised, you (in general) have no idea about the state of the process -- it may have corrupted heap, stack, global data internal to your test framework, global data internal to the C runtime system, etc. etc. Continuing such process is exceedingly likely to continue crashing at random (correct) places in the code.
The only sane way to handle this in a test framework is to fork and have the parent process handle child error exits, report them and continue running additional tests.
SIGABRT is a thread direct signal ?
There is no such thing as "direct signal". SIGABRT may be sent to the process from outside, or it can be raised inside the process.
What happens if I only use the main thread to catch the SIGABRT (or SIGSEGV) signal?
SIGSEGV and SIGABRT (when not sent from outside) is sent to the thread which caused the invalid memory operation (or raised it).
In addition, there is no way to "only use main thread" -- sigaction is global across all threads (though you can set a thread-specific signal mask).
I developed a C application in linux that contains an infinite loop while(1).
There are some pointers that are dynamically allocated and are useful under the infinite loop, so the only time to deallocate memory is after interrupting the while(1) by ctrl-z, ctrl-c, kill -9 apppid, killall appname.
So the idea is that I associate new handler that deallocates memory to the interruption events signals.
void deallocatehandler(int signal){ printf("Memory Deallocation\n"); exit(0);}
int main(){
signal(SIGINT, &deallocatehandler);
signal(SIGTSTP, &deallocatehandler);
signal(SIGKILL, &deallocatehandler);
while(1){
/**
Some code here
**/
}
}
If I press ctrl-c or ctrl-z the handler is called but the problem is with SIGKILL. The commands kill -9 and killall doesn't launch the handler.
Has someone an idea why? and is there suggestions to correct it?
The whole point of SIGKILL is to kill the process no matter what. That's why you're not allowed to handle it.
In most cases, you start with a SIGTERM to give the process a chance to exit nicely. SIGKILL is usually used as a last resort when SIGTERM does not work. After all, the expected behavior from SIGTERM is that the process exits. If it doesn't you know that something is wrong.
From the manual
The SIGTERM signal is a generic signal used to cause program termination. Unlike SIGKILL, this signal can be blocked, handled, and ignored. It is the normal way to politely ask a program to terminate.
...
The SIGKILL signal is used to cause immediate program termination. It cannot be handled or ignored, and is therefore always fatal. It is also not possible to block this signal.
In the same document, you can also read this interesting thing
In fact, if SIGKILL fails to terminate a process, that by itself constitutes an operating system bug which you should report.
You can't catch SIGKILL and SIGSTOP signals. So your signal handler wouldn't do anything.
There's nothing you can do when your process receives SIGKILL, let alone any memory cleanup.
On Linux, memory will be cleaned up on program exit, so this is probably not an issue.
Usually such cleanup-on-exit is done for SIGTERM.
The correct answer is don't send SIGKILL (kill -9 should only be used if kill itself doesn't work).
That's not the way to request to a process to terminate itself. Send SIGTERM first and if it doesn't work, then send SIGKILL.
man 7 signal
When you SIGKILL a process, you don't ask it to terminate nicely. You ask the kernel to stop any further execution for that process.
Thus, the process can't be aware it has received a SIGKILL.
But it shouldn't matter for you, since a SIGKILL shall only be issued when SIGTERM has shown no success.
So the idea is that I associate new handler that deallocates memory to the interruption events signals.
Not needed! After the process terminates, whatever the reason was, all memory is deallocated from the kernel. So you have no need to do that manually.
With IPC resources and semaphores you will have this problem which can't be handled properly at all.
Your question is ill-posed for several reasons.
First, malloced memory is freed when your process terminates. Most machines would be completely unusable if modern architectures wouldn't do this automatically.
Second, some signals and some ways of process termination aren't catchable. So for these there is no hope of doing repairwork anyhow. Among the methods that terminate an execution without much cleanup are some signals, abort, quick_exit, _Exit.
Third, using signalhandlers for cleanup jobs is complete overkill. The C library has atexit and at_quick_exit (since C11) handlers that are designed for that purpose. So if you have to do something special when an execution terminates (such as writing some final message to a socket, cleaning up files or shared memory) use the tools that were invented for this.
You can't catch SIGKILL (kill -9) by definition. It is meant as a "last resort" way to kill a process, so for this reason the process must not be able to catch it. For a friendly termination request, check for SIGTERM (kill -15 or kill without specific value).
But you should in general not want to catch such events, unless you need to do very specific clean-up actions. The memory will be deallocated but the Operating System; no need for your program to catch the signals only to free the memory.
I've recently had a problem with signals. I'd like to write a program in C which would print anything after a signal is sent to the process. For example: If I send SIGTERM to my process (which is simply running program), I want the program to print out for example, "killing the process denied" instead of killing the process. So how to do that? How to force process to catch and change the meaning of such signal. Also I have a question if there is any possibility to kill the init process (I know it's kind of a stupid question, but I was wondering how linux deals with such a signal, and how would it technically look if I type: sudo kill -9 1.
Don't use the signal handler to print. You can set a variable of type volatile sig_atomic_t instead, and have your main thread check this (see this example).
When your main thread has nothing else to do (which should be most of the time), let it block on a blocking function call (e.g. sleep()) that will wake up immediately when the signal is received (and set errno to EINTR).
C++ gotcha: Unlike the C sleep() function, std::this_thread::sleep_for() (in recent versions of glibc) does not wake up when a signal is received.
Regarding if it's possible to kill pid 1, see this question. The answer seems to be no, but I remember that Linux got very grumpy once I booted with init=/bin/bash and later exited this shell – had to hard reboot.
If you're looking for trouble, better kill pid -1.
I have a multi-threaded program. I want to handle all meaningful signals in a single thread. That's what I do before creating any thread:
sigset_t signal_set, old_set;
sigfillset(&signal_set);
// What signals should I leave unblocked here?
pthread_sigmask(SIG_SETMASK, &signal_set, &old_set);
std::thread( /* some args */ );
pthread_sigmask(SIG_SETMASK, &old_set, nullptr);
But my good sense suggests leaving some signals unblocked, since there is a plenty of situation when signals may be sent directly to specific thread: SIGSEGV or SIGPROF - I believe, it's as good as leaving unblocked SIGINT in an interactive program.
Are my suggestions correct about those two signals (SIGSEGV, SIGPROF)?
What other signals should I leave unblocked following some common sense?
Asynchronous signals (that's most of them, including anything sent by the kill command/function and signals generated by the controlling terminal like SIGINT) are deliverable to any thread in the process that has the signal unblocked, so there's no need to keep them unblocked in all threads. If you're using a dedicated signal handling thread, you want them blocked in all threads except the signal handling thread.
Synchronous signals on the other hand are delivered to a particular thread as a result of an action by that thread. They include SIGPIPE, SIGBUS, SIGSEGV, SIGFPE, etc. Except for SIGPIPE, none of these should happen at all unless you have serious bugs in your program, and you probably want to block SIGPIPE anyway so you can instead get the EPIPE error and handle this condition properly. So for the most part I would say it doesn't hurt to just block them all. If you really find yourself needing to handle SIGSEGV or such, you probably should rethink the reasons, but in the mean time feel free to unblock it.
I am trying to use sigwait() for SIGSEGV and other signals and then do something (says writing the timestamp to a file). Then, I would like the program to behave as if the signal were never caught (e.g. a coredump is generated when SIGSEGV happens -- assuming the system is configured for coredump).
I read through couple manpages, and I don't see an obvious way to do so.
Any suggestion?
Thanks in advance!
You can register a signal handler that won't cause the program to crash. Once you receive the signal, you'll enter the signal handler, and after executing the signal handler (write to file you said), you'll reenter the program where you left off.
If you want a core dump, you can use the linux core(5) command and it will create a core dump in your signal handler without ending your process.
http://www.alexonlinux.com/signal-handling-in-linux#signal_masks
I believe you can not handle few signals the way you want to for example
SIGKILL
SIGSEGV
as manual itself states The signals SIGKILL and SIGSTOP cannot be caught or ignored
check below links
SIGNAL(7) and SIGNAL(2) These links should provide good enough details on signal handling in linux
You can however register a signal handler to handle few other signals
to list signals in operating system like linux you can use below command
kill -l
and as far as generating core dump is conserned its generated by operating system click here for more info
check the example code here