Block signals for complete process in a multithreaded environment - c

I have a 'C' application in linux where in i have register SIGALRM handler. My SIGALRM handler updates some global data that other threads are also accessing.
Requirement:
In order to protect the global data, i need to block the signal completely while i am accessing it inside the thread. So i need a way to implement it.
Problem:
I am not able to block the signals completely.
sigprocmask is not working. Although it blocks signal if main is the only thread running. But when multiple threads are running SIGALRM keeps on coming.
I have tested pthread_sigmask but that updates the signal mask for current thread only.
Adding code logic:
sig_atomic_t atm_var;
void signal_handler()
{
atm_var++;
}
void thread_func()
{
pthread_sigmask(UNBLOCK,...);
while(1)
{
/* some stuff */
pthread_sigmask(BLOCK,...);
/* critical section, can easily access or modify atm_var */
pthread_sigmask(UNBLOCK,...);
}
}
int main()
{
sigprocmask(BLOCK,...);
pthread_create(...,thread_func,...);
sigaction(SIGALRM,...);
setitimer(ITIMER_REAL,...);
while(1)
{
}
}
Adding one more point: How safe it is to modify a sig_atomic_t variable (that signal handler is modifying) in main or other threads?
OR
Will it be safe practice to not to block signal while i modify the sig_atomic_t variable inside main or other threads?

Your problem is that various signals can be directed at the whole process or a particular thread. When directed at the whole process then they will be delivered to any thread that doesn't have them blocked.
man (7) signal
A process-directed signal may be delivered to any one of the threads that does not currently have the signal blocked. If more than one of the threads has the signal unblocked, then the kernel chooses an arbitrary thread to which to deliver the signal.
Because the signal masks are inherited by each thread from whatever thread created them, a fairly standard technique is to block them in the creator (for simplicity let's say that is main) and then let each spawned thread unblock signals as appropriate.
A common variation on this is to block them in main, and keep them blocked in all spawned threads except one. That one thread unblocks the signals and all process directed signals get aimed at it to handle.
The above is probably what you want to do. You probably are properly blocking SIGALRM in the thread which is running the signal handler. Unfortunately that isn't going to prevent SIGALRM from being delivered to a second thread.

Related

Does multi-thread program handle multiple signals in parallel?

Platform is Linux/POSIX.
The signal is sent to a whole process, not a specific thread.
No signal is set to blocked, all default.
The process is multi-thread process.
From what I've googled, a signal may be handled by a random thread.
And when that signal's handler is executing, it's temporarily blocked until handler returns.
QUESTION: Multiple signals of different types reached simultaneously. Do their handler execute simultaneously on multiple thread or all of them go to one randomly picked thread (SUB-QUESTION: in this case a handler could interrupt another handler's execution started previously, so there could be a interrupt stack?) ? Or mixed? For instance there are 3 type of signals received but only 2 thread free (this is actually the first case).
EXAMPLE: SIGHUP, SIGINT, SIGTERM reached almost simultaneously. The program has two available thread to dispatch signal handler execution.
SIDE-QUESTION: If signal handlers run in parallel, I'll have to use mutex to synchronize them properly. Otherwise 'volatile sig_atomic_t' would be enough, right?
Expected: all signals go to one thread (randomly picked) despite of their different signal types, I haven't seen an example of using mutexes and atoms to synchronize signal handlers.
Your understanding is correct - unless a signal was directed
to a specific thread, there's no guarantee which thread will handle a signal.
See POSIX's Signal Generation and Delivery and pthreads(7):
POSIX.1 distinguishes the notions of signals that are directed
to the process as a whole and signals that are directed to
individual threads. According to POSIX.1, a process-directed
signal (sent using kill(2), for example) should be handled by
a single, arbitrarily selected thread within the process.
So it may be delivered & handled by the same thread that's currently handling another signal (in that case, the previous handler may be interrupted by the new signal). Or may be delivered to another signal.
You can block other signals while one is being handled using sa_mask field
of sigaction to avoid a signal handler being interrupted.
SIDE-QUESTION: If signal handlers run in parallel, I'll have to use mutex to synchronize them properly. Otherwise 'volatile sig_atomic_t' would be enough, right?
You almost certainly don't want to use mutex in a signal handler. There are only few functions that can be safely called from a signal handler (you can only call the functions that are async-signal-safe).
See signal-safty for more information.
If you can use volatile sig_atomic_t for whatever the purpose (do you need to co-ordinate execution of different signal handlers?), it should be preferred.
Expected: all signals go to one thread (randomly picked) despite of their different signal types, I haven't seen an example of using mutexes and atoms to synchronize signal handlers.
This is commonly done by blocking signals that you're interested in from main and fetching/handling them in a specific thread. See pthread_sigmask which also has an example on how to implement this.

How to wait a signal in a thread?

I'm sending a signal from a module in the kernel space to a process. This process has one thread waiting for the signal.
I read the signal manual and it says:
The signal disposition is a per-process attribute: in a multithreaded application, including the disposition of a signal is the same for all threads.
Thus, and according to the manual pthread_sigmask:
http://man7.org/linux/man-pages/man3/pthread_sigmask.3.html
I'm trying to block the signal in the main function of the application by calling:
siginfo_t infoh1;
sigset_t waith1;
sigemptyset(&waith1);
sigaddset(&waith1, SIG_HILO1);
pthread_sigmask( SIG_BLOCK, &waith1, NULL );
Note that the thread is waiting for it in its execution function.
result = sigwaitinfo (&waith1, &infoh1);
The signal is sent, but the thread never receives it (it hangs waiting).
What am I doing wrong? I tested with different codes from different websites without success.
I use signals a lot in my *nix code and I don't think this is a good approach.
I recommend that all threads are set to ignore signals. The main process handles the signal while the thread sits on a mutex/condition. On signal the main process sets a global static flag with the signal type and then notifies the thread which duly checks the flag to see which signal was caught.
It's a safe and easy solution.

How sending a signal to a thread in c?

1-Sending unix signals is only possible to a processes, or it is also possible to send signals to threads?
2-Is it possible to send the tid of a thread to a kernel module? How?
3-In what way the kernel module can find the tid of a thread, to send a signal?
4-the thread will have a handler that will run on each signal. If each handler corresponds to a signal, are there any race conditions?
Can communicate a signal to all threads? What happens if all access the handler at a time?
Ad.1 From where do you want to send a signal? You can use kill() to send signal to process and pthread_kill() to send it to thread (but only from process which created thread).
Ad.3. While handling one signal, other pending signals will be queued, so there will be no race conditions. But you need to set non local variables used in handler to atomic (so when interrupt comes setting this variable will not be interrupted) and check which functions are handler safe.
About signals and threads - signal usually comes directly to process (only with pthread_kill you can send signal to thread from user space). If you have multithreaded process and none of thread has this signal blocked, then signal will come to random thread (the one which is running exactly when signal comes). If you block all threads but one, then signal will come to only this one thread.

pthreads: How to handle signals in a main thread that creates other threads? (specific code shown)

I have a main thread, which stays in the main function, i.e. I do not create it specifically as in pthread_create, because it's not necessary. This thread opens a file, then creates other threads, waits for them to finish their work (i.e., does the join), cleans up everything (pointers, semaphores, conditional variables and so on...).
Now, I have to apply this code to block SIGINT:
sigset_t set;
int sig;
sigemptyset(&set);
sigaddset(&set, SIGINT);
pthread_sigmask(SIG_BLOCK, &set, NULL);
while (1) {
sigwait(&set, &sig);
switch (sig) {
case SIGINT:
/* handle interrupts */
break;
default:
/* unexpected signal */
pthread_exit((void *)-1);
}
}
and it says You must use the main() function to launch the N+1 threads and wait for their completion. If a SIGINT signal arrives at the program it should be handled by the main thread in order to shutdown the program and its threads a clean way
My doubt is how should I put this code? Is it wrong to put it on a background thread created in main() ? Because I already have a cicle, with an exit flag, that creates and join all the other threads, so I don't understand if this code goes exactly to the main function where all is done/called to initiate the program. If I put it on a thread, with this code and the handler to clean, is this considerated as busy waiting?
"It says"? What says? The homework assignment?
The first thing you should understand about programming with threads and signals is that you have very little control over which thread a signal is delivered to. If your main thread wants to be the one to get the signal, it should block the signal before creating any new threads and possible unblock it after it finishes creating them, to ensure that the signal is not delivered to them.
However, if you're following best practices for signal handlers, it probably doesn't matter which thread handles the signal. All the signal handler should do is set a global flag or write a byte to a pipe (whichever works best to get the main thread to notice that the signal happened. (Note that you cannot use condition variables or any locking primitives from signal handlers!) As in the code fragment in your question, blocking the signal and using sigwait is also possible (be aware, again, that it needs to be blocked in all threads), but most programs can't afford to stop and wait just for signals; they need to wait for condition variables and/or input from files as well. One way to solve this issue is to make a dedicated thread to call sigwait, but that's rather wasteful. A better solution, if you're already using select, would be to switch to pselect that can wait for signals as well as file descriptor events (at the same time).
Rather than asking us for the answers (which would be hard to give anyway without seeing the full program you're trying to make this work with), you'd be much better off trying to really understand the intricacies of signals with threads.

Send and catch signals to pthreads in C

I know how to send signals to child process in C using the kill(pid_t pid, int sig) function. What about sending signals to threads? is it possible?. If so, how to catch signals on the "child" thread. For example, if the main thread sends me a terminate signal, how can I in the other thread catch it.
With POSIX threads, you have the functions pthread_cond_wait and pthread_cond_signal.
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex)
int pthread_cond_signal(pthread_cond_t *cond)
The signaled thread should block on a pthread_cond_wait call until another thread sends a signal using pthread_cond_signal, with the same condition variable.
Considering the analogy with signals delivered to processes, this is a bit different because the signaled thread has already suspended its execution waiting for a signal, unlike a process that simply gets interrupted and goes on.
Signals are sent to a process as a whole. Each signal sent to the process is received by a single thread (on behalf of the whole program). There are per-thread signal masks which influence whether a particular thread is eligible to handle a particular signal.
So, you need a signal handler - possibly in just one thread. Note that there are limits on what you're supposed to do in a thread's signal handler, though. Be wary of stepping far outside the promises made by the standard (which are minimal).
However, the pthread_kill() function can be used to send signals to other threads as long as the current thread can identify (has access to the thread ID values (pthread_t) that identify) the threads that are still executing within the process. You might decide to relay the signal to the other threads using a different signal number from the one originally caught (so one thread receives the external signal, but many threads receive the internal signal). Or you might use another Pthread synchronization or communication primitive instead of signals.
Signals do not have thread affinity. They are handled completely asynchronously. When you specify a signal handler with signal(2) or sigaction(2), it's a global signal handler. When a signal is raised, the signal handler runs on top of the stack of whatever thread happens to be running at the time, and you can't control that.
It sounds like you want some other sort of interthread communication. The simplest way to do this is with a volatile shared variable:
volatile bool should_terminate = false;
void ChildThread()
{
while(!should_terminate)
{
// do stuff
}
}
void MainThread()
{
// To terminate child thread:
should_terminate = true;
}
If you need stronger concurrency control, look into mutexes, condition variables, and semaphores.
I'm not sure this is possible as it is platform and implementation dependant and I highly suggest you don't use signals to communicate between threads. Sometimes only a specific thread will receive signals and sometimes all threads receive signals.
Better thread communucation mechanisms exist like queues, semaphores, and locks.

Resources