I'm looking for a way to, from within a signal handler, conditionally interrupt a syscall that way taking place at the time the signal was handled. To make this concrete, suppose a call to read is in process, and SIGRT0 is received. This signal handler uses SA_RESTART because it does not want to unconditionally interrupt syscalls, but depending on a condition, I want to cause read to return EINTR immediately once the signal handler returns.
One way I could do this is by setting up another signal handler for SIGRT1, putting SIGRT1 in the signal mask for SIGRT0's handler, and omitting SA_RESTART from the SIGRT1 handler. Then the handler for SIGRT0 can raise SIGRT1, and when the first, non-interrupting signal handler returns, the second one will fire and read gets interrupted.
The problem with this solution is that other processes could send SIGRT1, causing unwanted EINTR occurrences.
Is there any way to achieve the result I'm looking for?
If you want to set a particular process to send that signal then you can any IPC techniques (e.g. pipe) to share its pid id and flags to make sure that signal was sent by that process. If signal wasn't sent by the process then just ignore it.
What I wanted was impossible for multiple reasons. Perhaps most importantly, the secondary signal that was intended to do the interrupting would potentially (and in reality on most systems) fire as soon as the first signal handler returned but before the interrupted syscall got restarted. Then the syscall would restart and continue to block.
Perhaps more importantly, any attempt to interrupt blocking syscalls with EINTR intentionally is subject to race conditions where the signal arrives just before the blocking syscall, but after whatever check would have prevented making the syscall due to having received the signal. The only time this might be acceptable is when you're prepared to fire off multiple signals with increasing delays between them until the "interupt request" is honored, but that's getting into the realm of flaky hacks...
Related
is it necessary to check for errno == EINTR if you read massive amounts of data? I use the pread() function to read. In all my time I have never seen EINTR returned, but I have seen some code online where it is explicitely checks for it.
so really is it necessary to check for EINTR and maybe repeat the call?
EINTR is returned when as system call is interrupted as a result of your process receiving a signal. If your process was blocked in the kernel, waiting for the read to complete, and a signal is caught, this may wake the kernel; this depends on if the operation is interruptable. The sleeping I/O routine is woken and is expected to return EINTR to user-space.
Just before the kernel returns to user space, it checks for pending signals. If a signal is pending, it will take the action associated with that signal. Possible actions include: dispatching the signal to a signal handler, killing your process, or ignoring the signal. Assuming this does not kill your process and/or your signal handler returns normally, the system call will return EINTR.
If you were not expecting this, you typically want to try the action again, but this can also be used as a way to gracefully abort an I/O operation. For example, alarm(2) can be used to implement a timeout, where SIGALRM is delivered if the I/O does not complete in a timely manner. In your signal handler, you could set a flag indicating a timeout and when your read operation returns EINTR, you can check for your timeout flag.
The reason is - on a busy system, for example, it is possible to have an interrupt on the read.
So, on your desktop you may never see it. On an overloaded server, you can.
Se Chapter 5 of Advanced Programming in the UNIX Environment - Stevens and Rago. There is a complete explanation.
For theory purpose: I associate handler for SIGINT, by using signal (). When the this signal is handled, ie, signal handler is executed, by default the same signal is blocked. What is the reason behind blocking ?. Does it lead to deadlock kind of situation ? Kindly clarify.
Because signal handlers are not expected to be re-entrant.
A signal handler typically runs quickly and should call only async safe functions, i.e. a very restricted set of functions, see signal(7).
You usually don't want it to be callable inside itself.
Unless you don't return normally from the signal (or do a siglongjmp inside it), the previous signal masks are restored after the signal handler completed.
However, you can install a signal handler (thru sigaction) which does not block itself.
For similar reasons, on usual processors, the intterupt handlers are also running quickly and are disabling interrupts.
I am aware that i can mask a signal from being raised when handler is executing (by using sa_mask). However, i would like to know how to mask a signal when i am updating some global variables.
Also, i would like to know how to mask a signal when a particular user defined function is executing.
Is it possible to do these 2 things?
Any help will be appreciated
Thanks
You can call "signal()" any time you want; either to a) set the signal handler to some custom code, or b) clear it by setting the handler argument to NULL.
sigaction(), of course, gives you even finer-grained control. You can call sigaction whenever you wish (for example, before updating your global variables), too.
This link might help:
http://www.linuxjournal.com/article/6483
It's possible to block signals with sigblock(). Signals blocked will be queued and released when the signal is unblocked.
HOWEVER - this is super expensive. You have to do a syscall to block and a syscall to unblock. This can be quite slow if you do it often. So there are some alternative approaches:
If you're on linux, use signalfd. You can block all signals once and redirect them to a file descriptor, then handle them whenever it's safe to do so.
Otherwise (or if async signal handling is important), you can defer signals in userspace. Before entering your critical section, set a volatile flag. In your signal handler, check for this flag; if you see it, write() to a pipe the signal number and immediately return. In your signal handler, check back for a signal on this pipe, and re-raise the signal at that point.
I've got a situation where a signal handler needs to, under certain conditions, return without unmasking itself, i.e. after returning the signal should remain blocked in the thread's signal mask. Jumping out of the signal handler with longjmp will not work because I need to return to the exact point that was interrupted like a normal signal handler return. Is there any conformant way to do this, short of using the ucontext_t which was removed from the standards? I cannot change signal handlers or dispositions; all effects must be local to the thread.
The purpose of this code has to do with some atomic operations and potential for a race condition or deadlock. Basically the potentially interrupted code looks like:
atomic_write(&thread_local_flag, 1);
atomic_dec(&global_counter);
If the flag has been set and the counter decremented, all is well and the signal handler has nothing to do, but the signal could possibly arrive between the two instructions. In this case, the signal handler wants to immediately return and let the decrement proceed, but the process is being bombarded with signals (intended to be received by all threads for an arcane synchronization purpose) and there's a possibility it could loop forever (or at least for unbounded time) processing signals while other threads never receive their signals.
If I could leave the signal blocked when the signal handler returns, there would be no problem.
Hmm, the best I've found so far.. This seems to work and does not depend on any ucontext functions, just the structure which was not removed. In the signal handler:
if (thread_local_flag) {
sigaddset(&((ucontext_t *)ctx)->uc_sigmask, sig);
return;
}
Here sig and ctx are the first and third argument to the SA_SIGINFO-type signal handler, respectively.
Any thoughts on whether this is correct usage or a horrible hack (or both)?
Without keeping a list of current threads, I'm trying to see that a realtime signal gets delivered to all threads in my process. My idea is to go about it like this:
Initially the signal handler is installed and the signal is unblocked in all threads.
When one thread wants to send the 'broadcast' signal, it acquires a mutex and sets a global flag that the broadcast is taking place.
The sender blocks the signal (using pthread_sigmask) for itself, and enters a loop repeatedly calling raise(sig) until sigpending indicates that the signal is pending (there were no threads remaining with the signal blocked).
As threads receive the signal, they act on it but wait in the signal handler for the broadcast flag to be cleared, so that the signal will remain masked.
The sender finishes the loop by unblocking the signal (in order to get its own delivery).
When the sender handles its own signal, it clears the global flag so that all the other threads can continue with their business.
The problem I'm running into is that pthread_sigmask is not being respected. Everything works right if I run the test program under strace (presumably due to different scheduling timing), but as soon as I run it alone, the sender receives its own signal (despite having blocked it..?) and none of the other threads ever get scheduled.
Any ideas what might be wrong? I've tried using sigqueue instead of raise, probing the signal mask, adding sleep all over the place to make sure the threads are patiently waiting for their signals, etc. and now I'm at a loss.
Edit: Thanks to psmears' answer, I think I understand the problem. Here's a potential solution. Feedback would be great:
At any given time, I can know the number of threads running, and I can prevent all thread creation and exiting during the broadcast signal if I need to.
The thread that wants to do the broadcast signal acquires a lock (so no other thread can do it at the same time), then blocks the signal for itself, and sends num_threads signals to the process, then unblocks the signal for itself.
The signal handler atomically increments a counter, and each instance of the signal handler waits until that counter is equal to num_threads to return.
The thread that did the broadcast also waits for the counter to reach num_threads, then it releases the lock.
One possible concern is that the signals will not get queued if the kernel is out of memory (Linux seems to have that issue). Do you know if sigqueue reliably informs the caller when it's unable to queue the signal (in which case I would loop until it succeeds), or could signals possibly be silently lost?
Edit 2: It seems to be working now. According to the documentation for sigqueue, it returns EAGAIN if it fails to queue the signal. But for robustness, I decided to just keep calling sigqueue until num_threads-1 signal handlers are running, interleaving calls to sched_yield after I've sent num_threads-1 signals.
There was a race condition at thread creation time, counting new threads, but I solved it with a strange (ab)use of read-write locks. Thread creation is "reading" and the broadcast signal is "writing", so unless there's a thread trying to broadcast, it doesn't create any contention at thread-creation.
raise() sends the signal to the current thread (only), so other threads won't receive it. I suspect that the fact that strace makes things work is a bug in strace (due to the way it works it ends up intercepting all signals sent to the process and re-raising them, so it may be re-raising them in the wrong way...).
You can probably get round that using kill(getpid(), <signal>) to send the signal to the current process as a whole.
However, another potential issue you might see is that sigpending() can indicate that the signal is pending on the process before all threads have received it - all that means is that there is at least one such signal pending for the process, and no CPU has yet become available to run a thread to deliver it...
Can you describe more details of what you're aiming to achieve? And how portable you want it to be? There's almost certainly a better way of doing it (signals are almost always a major headache, especially when mixed with threads...)
In multithreaded program raise(sig) is equivalent to pthread_kill(pthread_self(), sig).
Try kill(getpid(), sig)
Given that you can apparently lock thread creation and destruction, could you not just have the "broadcasting" thread post the required updates to thread-local-state in a per-thread queue, which each thread checks whenever it goes to use the thread-local-state? If there's outstanding update(s), it first applies them.
You are trying to synchronize a set of threads.
From a design pattern point of view the pthread native solution for your problem would be a pthread barrier.