SIGSEGV sent twice - crashes program after being handled - c

I have a test program for part of a C library where I handle signals. There is a lot of code in this test program - so much that I feel that posting it here would only make it more difficult to answer my question.
Basically what's happening is that I am forcing the system to send me a SIGSEGV inside a background thread. I handle that signal, and then the test is over. The main thread will be waiting for this and part of the signal handler is to restart the main thread. When the main thread restarts I restore the default signal handler by signal(SIGSEGV, SIG_DFL) and then I get another SIGSEGV.
I understand that I have a lot of code and this could very well be my fault, but is there a common explanation of why a SIGSEGV would fire twice? It is not happening when I cause other signals (though I haven't tried all of them).
To clarify I am on OS X, writing in C, compiling with gcc.

If you have any problem inside the signal handler, for example, memory overwrite, trying to access beyond the allocated area, then a new signal will be raised. Check the following page for details.
http://www.gnu.org/software/libc/manual/html_node/Signals-in-Handler.html
You should also use reentrant functions inside the signal handlers, For example localtime_r instead of localtime.
Moreover it is recommended to use sigaction() instead of signal().
More details here: What is the difference between sigaction and signal?

Related

C write async unsafe code in signal handler

How can i run asynchrounous-unsafe code in a signal handler. I cant use a flag in my case. Could i use longjmp to jump to a different context?
In a signal handler you can only use a set of safe functions which in many cases is sufficient for complicated functionality started within a handler. You can check man pages for your system for 'signal-safety' or similar. Here is a pointer on the web: https://man7.org/linux/man-pages/man7/signal-safety.7.html
pthread synchronization functions are not on the list.
However, One of the function listed there is sem_post: https://man7.org/linux/man-pages/man3/sem_post.3.html
sem_post() is async-signal-safe: it may be safely called within a
signal handler.
So, you can implement mutex-like synchronization using semaphores within the signal handler.

Can I execute free() or close() in a signal handler? [duplicate]

This question already has answers here:
How to avoid using printf in a signal handler?
(8 answers)
Closed 2 years ago.
I have a code that looks like this:
//global variables
void signal_handler() {
//deallocation of global variables
free(foo);
close(foo_2);
exit(0);
}
int main () {
signal(SIGINT, signal_handler);
//irrelevant code
}
As you can see, I changed the CTRL+C interruption to execute the signal_handler function once instead of killing the process right away. I read somewhere that some functions like might be free are not async-safe and would NOT execute in the signal_handler but I'm not sure about that.
Can I execute functions like free, close, exit or even pthread_join in a signal handler?
No. Only functions listed in man 7 signal-safety are safe to call inside a signal handler.
close is listed and should be safe. free is not. For reasons why you would have to look at its source code (it contains locks). exit is not safe because it can call arbitrary cleanup handlers. You have _exit which exits abruptly without the cleanup.
You techincally can compile a program that calls such functions in a signal handler, nothing stops you from doing that. However it will result in undefined behavior if the function you are trying to execute is not async-signal-safe. It's not like unsafe function would just "NOT execute" as you say, they very well could, but that'd still be undefined behavior.
A list of async-signal-safe functions is documented in man 7 signal-safety. The close() function is safe, while free() and phtread_join() are not. The exit() function is also not safe to call from a signal handler, if you wish to exit from such context you will have to do so using _exit() instead.
The only way to safely call a function that is not async-signal-safe when receiving a signal is to "remember" that you have to call it (for example setting a global variable) and then do so after returning from the signal handler.
Short answer is no:
7.1.4 Use of library functions
...
4 The functions in the standard library are not guaranteed to be reentrant and may modify
objects with static or thread storage duration.188)
188) Thus, a signal handler cannot, in general, call standard library functions
C 2011 Online Draft
Real-world example of the consequences - I worked on a system that communicated with an Access database. There was a signal handler that tried to write an error message to the console with fprintf, but somehow during the signal handling process stderr got mapped to the .mdb file that stored the database, overwriting the header and ruining the database beyond repair.
There's honestly not a whole lot you can do in a signal handler other than set a flag to be checked elsewhere.
Can I execute free() or close() in a signal handler?
You definitely should not. See signal(7) and signal-safety(7)
In practice, it might work like you want perhaps more than half of the time. IIRC, the GCC compiler is doing like you want to do, and it usually works.
A better approach is to use some write(2) to a pipe(7) (from inside your signal handler) and from time to time check that pipe (in your main program) with poll(2) or related things.
Or you could set some volatile sigatomic_t flag; (perhaps it should be also _Atomic) in your signal handler, and check that flag elsewhere (in the main program, outside of signal handlers).
Qt is explaining that better than I could do in a few minutes.
On Linux, see also signalfd(2) and eventfd(2).

Catching Segmentation Violations and Getting on with Life

I'm writing a program that's examining its own address space.
Specifically, I care about all malloc-ed data blocks. If there some system call to get a list of them, that would be fantastic (for my application, I cannot use LD_PRELOAD, -wrap, nor any extra command line options). If there's a way to do this, I'd love to hear it even more than an answer to my stated problem, below.
In lieu of this, my current approach is to just dereference everything and look around. Obviously, the set of all possible pointers is a minefield of segfaults waiting to happen, so I tried registering a signal handler and using setjmp/longjmp (simply ignoring the segfault by making the handler do nothing is an infinite loop because the handler will return to the faulting instruction). Some example code goes like so:
static jmp_buf buf;
void handler(int i) {
printf(" Segfaulted!\n");
longjmp(buf,-1);
}
void segfault(void) {
int* x = 0x0;
int y = *x;
}
void test_function(void) {
signal(11,handler);
while (1) {
if (setjmp(buf)==0) {
printf("Segfaulting:\n");
segfault();
}
else {
printf("Recovered and not segfaulting!\n");
}
printf("\n");
}
}
The output is:
Segfaulting:
Segfaulted!
Recovered and not segfaulting!
Segfaulting:
Segmentation fault
So, the handler didn't work the second time around. I don't know why this is, but I speculated it had something to do with not clearing the original signal. I don't know how to do that.
As an aside, I tried sigsetjmp/siglongjmp first, but they weren't defined for some reason in setjmp.h. I got vague vibes that one needed to pass some extra compile flags, but, as before, that is not allowed for this application.
The system being used is Ubuntu Linux 10.04 x86-64, and any solution does not need to be portable.
[EDIT: sigrelse in the handler clears the signal, and fixes the problem effectively. Question now concerns the other issues raised--is there a better way (i.e., get the blocks of malloc)? What's up with sigsetjmp/siglongjmp? Why do I need to reset the signal?]
signal() is a legacy interface, and may or may not re-register a signal handler after it has been invoked, depending on the OS; you may need to issue another signal() call to reset the signal handler as the last action in your handler. See man 2 signal.
sigaction() is the preferred mechanism to set signal handlers, as it has well defined and portable behavior.
When the signal handler for SIGSEGV is invoked, the SIGSEGV signal will be masked as if by sigprocmask. This is true for any signal. Normally returning from the signal handler would unmask it, but since you're not returning, that never happens. There are a couple possible solutions:
You can call sigprocmask either before or after the longjmp to unmask it yourself.
You can install the signal handler with sigaction (the preferred way to do it anyway) and use the SA_NODEFER flag to prevent it from being masked.
You can use the sigsetjmp and siglongjmp functions, which themselves take responsibility for saving and restoring the signal mask.

Race condition in C signal handlers puzzle

I need to know how to avoid a race condition when handling signals in C. Each time my program receives a signal, I want it to alter a (global) linked list. It is vitally important that I not miss a signal, and equally important that the global linked list I'm modifying not be changed while the handler is executing.
The problem is, if I receive a signal, and start the handler, but am then interrupted by another signal. This (as I understand it) triggers a new execution of the signal handler, which will operate on the same global dataset - not permissible!
I can't use a lock, because if the first handler call is interrupted, it will naturally never free the lock for the interrupting handler to pick up. So, how do I do it? Any idea?
If you have the luck to be working in a multi-threaded environment, one of the best ways is to have the global linked list controlled exclusively by a separate thread. Interrupts would enqueue requests to this thread (something that would be executed very quickly, say, by simply passing a pointer), and then the thread would procedurally go through each request and modify the linked list. This allows lockless execution.
Of course, you have to rely on your OS's message passing junk, so that may not be an option.
You can mask signals while executing signal handler - check sa_mask field of struct sigaction you pass to sigaction() syscall.
From http://users.evtek.fi/~tk/rtp/signals-programming.html:
The way to guarantee no races at all, is to let the system set the signal masking for us before it calls the signal handler. This can be done if we use the sigaction() system call to define both the signal handler function AND the signal mask to be used when the handler is executed. You would probably be able to read the manual page for sigaction() on your own, now that you're familiar with the various concepts of signal handling. On old systems, however, you won't find this system call, but you still might find the sigvec() call, that enables a similar functionality.
I think you should seriate the signal.just like the work queue
E.g. all the signal should put into a work queue(FIFO), and then the executing thread poll the queue all the time. if the queue is not empty,this thread will pick the top signal and start it`s handler. keep doing like that, until the queue is empty.

What happens if during a signal handling in UNIX, the same signal gets sent to the program?

Any ideas on this? Is there some kind of a signal queue, or does it get dropped?
While we are at this question, is it true that signal handlers should do as minimal work as possible?
I read somewhere that a signal handler should use a pipe and just write one byte to it, indicating what the program should do. Then somewhere else the program periodically checks the pipe, and dispatches based on byte in it. (I might have misunderstood it)
Thanks, Boda Cydo.
To answer the second part of your question, "is it true that signal handlers should do as minimal work as possible?" the answer is yes, because there is a very minimal set of functions that are "async signal safe" and therefore able to be called from signal handlers. Async signal safety is kind of an enhanced form of re-entrancy. If foo() is async signal safe, that means that it's safe to call foo() within a signal handler, even if foo() was already executing when the signal was raised.
You can get the full list of async signal safe functions by looking that the section 7 man page for signal (man 7 signal). Calling any function other than one of these from within a signal handler, directly or indirectly, invokes undefined behavior.
The "write a byte to a pipe" approach is a great way to deal with signals without being restricted to async signal safe functions, especially if your program is already oriented around a select loop.
To answer the first part of your question, the default is as follows: If it's the same signal as the one currently being handled, the new signal is blocked (held in a queue) and delivered when the handler returns. If some other signal arrives, the handler for the new signal is called. c.f. the glibc manual.

Resources