C write async unsafe code in signal handler - c

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.

Related

Creating a thread in signal handlers

In my program I need to perform some action upon timer (timer_create()) expiration. I want to perform this action by spawning a new thread. So I want to know if it is safe to create a thread in signal handlers?
Signal handlers may not call non re-entrant functions. You should look at your o/s documentation but creating a thread is unlikely to be re-entrant. On linux, man -s7 signal gives you a list of safe to call functions, which doesn't include anything from pthread.
Really all a signal handler should do is to set a flag for the main code or a signal handling thread to read. More than that gets risky.

(f)printf() thread-safe but not signal-handler safe

We recently had a discussion at work about signal handlers in C (Unix enviornment).
Someone mentioned that
(f)printf() is certainly thread-safe but not signal-handler safe.
What does the above statement mean? What aspect of (f)printf() make it not signal-handler safe? Is it because it accesses the stdout and stdin which are global and hence the function is not re-entrant?
Or is there some other aspect which I am missing?
There is actually fairly little that is legal to do in a signal handler directly. Instead, one must usually set some flag or trigger to do the real work outside the signal handling context. While handling a signal, the only functions you can call are those which are "async signal safe," which is described in detail here: What constitutes asynchronous-safeness
As mentioned in here: http://www.gnu.org/software/libc/manual/html_node/Nonreentrancy.html#Nonreentrancy
If a function uses and modifies an object that you supply, then it is
potentially non-reentrant; two calls can interfere if they use the
same object.
In your case that object is stdout. When a signal arrives in the middle of a (f)printf() and if you use (f)printf in handler, both data could be corrupted as they operate on the same stream, stdout. Reentrancy is the root cause in that case. Even if you use the stream in just signal handler, two signal handlers can interfere.

What constitutes asynchronous-safeness

It is said that you should only call asynchronous-safe functions inside a signal handler. My question is, what constitutes asynchronous-safeness? A function which is both reentrant and thread safe is asynchronous-safe I guess? Or No?
Re-entrance and thread safety has a little or nothing to do with this. Side effects, state and interruption of those functions are facts that matter.
asynchronous-safe function [GNU Pth]
A function is asynchronous-safe,
or asynchronous-signal safe, if it can be called safely and without
side effects from within a signal handler context. That is, it must be
able to be interrupted at any point to run linearly out of sequence
without causing an inconsistent state. It must also function properly
when global data might itself be in an inconsistent state. Some
asynchronous-safe operations are listed here:
call the signal() function to reinstall a signal handler
unconditionally modify a volatile sig_atomic_t variable (as
modification to this type is atomic)
call the _Exit() function to
immediately terminate program execution
invoke an asynchronous-safe
function, as specified by your implementation
Few functions are
portably asynchronous-safe. If a function performs any other
operations, it is probably not portably asynchronous-safe.
A rule of thumb is this - only signal some condition variable from signal handler (such as futex/pthread condition, wake up epoll loop etc.).
UPDATE:
As EmployedRussian suggested, even calling pthread_cond_signal is a bad idea. I've checked the source code of the recent eglibc and it has lock/unlock pair in there. Thus, introducing a possibility for a deadlock. This leaves us with few options to signal other threads:
Using eventfd.
Changing global atomic variable and hope that SA_RESTART is not set and other threads will check our atomic.
For your own code, yes, re-entrant and thread-safe are the characteristics you need, as, depending on how you set up your signal handling mechanism, your signal handler may itself be interrupted by another signal. In general, try to do as little work as possible inside the signal handler. Setting flags to trigger special code in your normal program flow is probably all you should be doing.
For functions in the OS that you might call, check out man 7 signal for a list of what is safe to call. Note that malloc() and free() are not on the list. The pthread synchronization APIs are not on the list either, but I would think that some would have to be safe to call, so you can set a global flag safely in a signal handler.

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