Fellow coders.
If I send a SIGINT signal to a thread stuck on pthread_cond_wait(), when sign_handler() returns, will pthread_cond_wait() return as well?
If not, is there any way to make pthread_cond_wait() return?
If I send a SIGINT signal to a thread stuck on pthread_cond_wait(), when sign_handler() returns, will pthread_cond_wait() return as well?
No.
If not, is there any way to make pthread_cond_wait() return?
No, you're trying to use the wrong tool to solve whatever underlying problem you have.
(Technically, pthread_cond_timedwait() is allowed to return when interrupted by a signal delivery, but it does not do so, at least when using GNU glibc 2.27 on x86-64 running kernel 5.3.0. Yes, I checked.)
How can I fix my problem?
Let's assume that a condition variable is the best option for your use case. (That's just a guess, though; you didn't tell us about your real problem you're trying to solve, only how your chosen solution isn't working.)
Then, the recommended solution is to use a helper thread to catch signals like SIGINT, using sigwaitinfo() or sigtimedwait(). That helper thread can then set a specific volatile sig_atomic_t you_need_to_exit flag, and pthread_cond_signal() or pthread_cond_broadcast() on the relevant condition variables to let them know something important happened. Those waiting on the condition variables should obviously first check the helper flag; and if set, assume that that was the source for the wakeup signal. Usually I name such flags need_to_exit or similar.
The key in such signal handling helper threads is that the signals need to be blocked in all threads (including the handling helper thread itself). It is best to do this in the main thread before creating any other threads, as then the created threads inherit that same signal mask.
The siginfo_t structure contains all kinds of useful information. Most useful is perhaps the .si_pid field, which tells which process (or 0 if kernel) sent the signal. That way, if you use say SIGRTMIN+0 to SIGRTMAX-0 signals for internal purposes, you can ignore them unless they come from the process itself (other threads, .si_pid == getpid()).
Thread cancellation (deferred, at cancellation points; pthread_cond_wait() being a cancellation point) is another option. You can use pthread_cleanup_push() to set/add functions to be run if the thread is cancelled. This basically forcibly kills the target thread, but it can run any cleanup functions it has set up before it dies. You can also defuse any cleanup functions using pthread_cleanup_pop() -- a parameter specifies whether the cleanup function is run and discarded, or just discarded. But, when cancelled, the thread always dies.
Do use pthread_attr_t to limit the stack size to a sane power of two. If you don't have any large arrays or structures on stack (local variables), then something like
#include <limits.h>
#ifndef THREAD_STACK_SIZE
#define THREAD_STACK_SIZE (4 * PTHREAD_STACK_MIN)
#endif
with
sigset_t mask;
pthread_attr_t attrs;
int err;
/* Block SIGINT in this (and all created threads) */
sigemptyset(&mask);
sigaddset(&mask, SIGINT);
err = pthread_sigmask(SIG_BLOCK, &mask, NULL);
if (err) {
fprintf(stderr, "Cannot block signals: %s.\n", strerror(err));
return EXIT_FAILURE;
}
/* Create stack size attribute. */
pthread_attr_init(&attrs);
pthread_attr_setstacksize(&attrs, THREAD_STACK_SIZE);
/*
* Create threads, use &attrs for the second parameter.
*/
/* Optional cleanup - it's a good idea to be careful. */
pthread_attr_destroy(&attrs);
should work fine, for both stack size and blocking some signals in all threads (by blocking them first in the thread that creates the other threads; they'll inherit the signal mask).
You can add any other signals to the blocked mask you like, except that SIGKILL and SIGSTOP cannot be blocked, caught, or ignored.
The pthread_attr_t second parameter to pthread_create() is just a collection of settings (or attributes), like configuration; they are not "consumed" by the pthread_create() call. You can use the same set of attributes any number of times. This one contains only the desired stack size. (It does not contain the stack itself, only the desired size.)
The default stack size is very large, typically 8 MiB, which means that a lot of virtual memory is reserved for thread stacks for no good reason, really. Also, it severely limits the number of threads a process can create.
In many ways, having a helper thread for signal handling is easier than actual signal handlers, because only async-signal safe functions are safe to use in a signal handler; whereas in the helper thread, you can use all.
Related
I want the process exit when it receive an exit signal. So the main thread needs to wait for the exit signal, which I wrote like this before.
int signal(int a) {
exit_flag = 0;
}
//wait in main thread
while(exit_flag){
sleep(1);
}
But it reacts a little slowly. So I find a new method like this,
//signal function
int signal(int a) {
pthread_mutex_unlock(&mutex);
}
//main thread
pthread_mutex_lock(&lock);
pthread_mutex_lock(&lock);
I'm not sure if it's correct. My question is that if it's a propper way to wait for an exit signal or you can tell me a better way?
Sincerely thank you all for your replies.
I know that it's undefined beahiver and unsafe to use the mutex in signal handler. But is the above code correct if I send the exit message through some other method, like a jrpc call or something like that?
My question is that if it's a propper way to wait for an exit signal or you can tell me a better way?
No, for reasons that #AndrewHenle describes very well in his answer.
There are multiple correct ways to do it, but many of them reinvent the wheel of the pause() function and its improved alternative sigsuspend(). These two are specifically for the purpose of waiting for a signal to be delivered. The Glibc manual contains a section on how to use them for the purpose.
Alternatively, if your process is multithreaded and you want to devote only one thread to waiting, then there is sigwait(), sigwaitinfo() and sigtimedwait().
For the whole process to wait
Suppose you want the whole process to stop until a SIGUSR1 is delivered to it, then exit. After installing your signal handler, you might use something like this:
// sufficient for this case even in a multi-threaded program:
volatile sig_atomic_t exit_flag;
// ...
/*
* Wait, if necessary, until a SIGUSR1 is received, then exit with status 0.
*
* Assumes that a signal handler for SIGUSR1 is already installed, that the
* handler will set variable `exit_flag` to nonzero when it runs, and that
* nothing else will modify exit_flag incompatibly.
*/
void wait_to_exit(void) {
sigset_t temp_mask, mask;
sigemptyset(&temp_mask);
sigaddset(&temp_mask, SIGUSR1);
/*
* Temporarily block the signal we plan to wait for, to ensure that we
* don't miss a signal.
*/
sigprocmask(SIG_BLOCK, &temp_mask, &mask);
// Prepare to wait for the expected signal even if it is presently blocked
sigdelset(&mask, SIGUSR1);
// if we haven't already received the signal, then block the whole process until we do
while (!exit_flag) {
sigsuspend(&mask);
}
// No need to reset any signal masks because we're about to ...
exit(0);
}
About the flag's data type
To expand on one of the comments in the above code, volatile sig_atomic_t is a sufficient type for the purpose even in a multithreaded program. sigsuspend() is specified to return after the signal handler returns, and the signal handler will not return until after the write to the flag actually happens (because of volatility). The thread calling sigsuspend must then read the value that was written by the handler, or some other value subsequently written to the same variable, again because of volatility.
volatile typically is not enough for thread safety, however, so even though it is not necessary in this case, you could consider sidestepping the issue and any uncertainty about it by instead using atomic_flag (declared in stdatomic.h); this requires support for C11 or later.
For just one thread to wait
For the case of one thread out of many waiting for a signal, it should be structured rather differently. You do not need a signal handler or flag in this case, but you should block the expected signal for all threads via sigprocmask():
sigset_t mask;
sigemptyset(&mask);
sigaddset(&mask, SIGUSR1);
sigprocmask(SIG_BLOCK, &mask, NULL);
That prevents the default (or custom) disposition of the expected signal from being executed in any thread, and ensures that threads other than the one that is to wait do not consume the signal. Typically, it should be done very early in the program's execution.
Then, to await the signal, a thread does this:
void wait_to_exit(void) {
sigset_t mask;
int sig;
sigemptyset(&temp_mask);
sigaddset(&temp_mask, SIGUSR1);
// if we haven't already received the signal, then block this thread until we do
if (sigwait(&mask, &sig) != 0) {
// Something is terribly wrong
fputs("sigwait failed\n", stderr);
abort();
}
assert(sig == SIGUSR1);
// Terminate the process (all threads)
exit(0);
}
If you mean a generic "signal"
If you mean "signal" as a generic term for a synchronous notification, as opposed to an exercise of the C signal-handling facility, then #AndrewHenle's suggestion of a semaphore would be perfect. In that case, be sure to accept that answer.
No, it is not correct.
First, pthread_mutex_unlock() is not an async-signal-safe function and can not be safely called from within a signal handler.
Second, mutexes are locked by a thread. If the signal handler is run in a different thread than the thread that has the mutex locked, it can not unlock the mutex:
If a thread attempts to unlock a mutex that it has not locked or a mutex which is unlocked, pthread_mutex_unlock() shall behave as described in the Unlock When Not Owner column of the following table.
The only entries in that table are "undefined behavior" and "error returned". And you have no real control over which thread the signal will be delivered to (at least not without writing complex signal-handling code...)
Third, this code
pthread_mutex_lock(&lock);
pthread_mutex_lock(&lock);
per that same table, will not block safely for any type of mutex. That code will either deadlock, continue with the mutex locked, or invoke undefined behavior which might even appear to "work" but leaves your program in an unknown state that could cause errors later.
Edit:
Fourth, if the signal is delivered multiple times, multiple calls to pthread_mutex_unlock() will again result either in errors or undefined behavior.
But there is an async-signal-safe way to block waiting for a signal: sem_wait().
sem_post() is async-signal-safe and can safely be called from within a signal handler, and can also be call multiple times safely - multiple calls to sem_post() will merely allow a corresponding number of calls to sem_wait() to obtain the semaphore, but you only need one to work:
//signal function
int signal(int a) {
sem_post(&sem);
}
//main thread
sem_wait(&sem);
Note that it is not safe to call sem_wait() within a signal handler.
Besides accepting signals (via sigwait or sigtimedwait), I'm a fan of the venerable self-pipe trick: "Maintain a pipe and select for readability on the pipe input. Inside the [signal] handler, write a byte (non-blocking, just in case) to the pipe output."
I'd further add to the above that the signal handler ought to be installed by sigaction as SA_RESTARTable.
Now you can safely mix the signal delivery with IO (via select or poll, e.g., or just blockingly read until that byte comes across).
In a single threaded program, does a race condition is possible in a signal handler?
void signal_handler(...)
{
static int i = 0;
i = i + 10 * 10;
}
Imagine that two very close signals are thrown, so close that they enter the function at the same time.
I can't find informations about how recent Linux OS handle this. I just know that both signals are correctly handled but I don't know how. Does race conditions are possible ?
Any helps appreciated, thanks!
There is no race condition in the sense that you mean (between two signals). Multiple signals of the same signal are not delivered simultaneously. Unless precautions are taken, multiple signals for different signal numbers may be delivered simultaneously, as described in torek's answer.
Whenever you involve variables of static duration (or global variables), your function may no longer reentrant. This is typically not important for the signal handler function itself. However, if it calls some other function that accesses global or static data, then that function will see an access pattern that is similar to two threads racing through a critical section. That is, your program is calling such a function to do its normal processing, but the signal arrives in the middle of that function, and then your signal handler calls into that same function. The global/static variables may be in an inconsistent state, and might cause your program to have non-deterministic behavior.
POSIX defines a set of APIs that are safe to be called from within a signal handler. Your code should take similar precautions when you plan to let your signal handler call functions that you implement.
Single threaded means only one app touching the static at a time yes? If there are 2 apps, there are 2 statics and no race condition.
If this is an interrupt handler and i += 100 is not atomic (which it may be depending on the platform/CPU), then it would race.
One additional, important note: if you're using "reliable signals" (POSIX sigaction with the corresponding sa_mask field), you get control over how signals behave in a single-thread-single-process situation.
Consider the case of single process P1, with a signal-handler like the one you show above. Suppose that you are catching signal SIGUSR1 and having that enter the function signal_handler. While you are inside signal_handler, some other process P2 sends another SIGUSR1 to P1 (e.g., via kill). This signal is "blocked" (temporarily) via sa_mask until signal_handler returns in P1. This is true even if you don't set any bits in sa_mask (as long as you don't set SA_NODEFER in sa_flags, see below).
But, suppose you've also decided to catch SIGUSR2 with function signal_handler. Suppose that P2 also sends a SIGUSR2. In this case, the SIGUSR2 is (or may be) caught, starting another instance of signal_handler running, this time on behalf of the SIGUSR2 signal.
You can prevent this by making sure that when SIGUSR1 is being handled, SIGUSR2 is temporarily blocked as well. In general you'd probably want to make SIGUSR1 blocked while SIGUSR2 is being handled. To do this, set both corresponding bits in sa_mask:
struct sigaction sa;
memset(&sa, 0, sizeof sa);
sa.sa_flags = SA_RESTART | SA_SIGINFO; /* (decide for yourself which flags) */
sigaddset(&sa.sa_mask, SIGUSR1);
sigaddset(&sa.sa_mask, SIGUSR2);
sa.sa_sigaction = signal_handler;
error = sigaction(SIGUSR1, &sa, NULL);
if (error) ... handle error ...
error = sigaction(SIGUSR2, &sa, NULL);
if (error) ... handle error ...
The two sigaddset calls make sure that both SIGUSR1 and SIGUSR2 are held-off (blocked, temporarily) for the duration of the function.
If you're only catching one signal, there is no need for this extra complexity, because as long as SA_NODEFER is not set, the OS automatically adds whatever signal triggered entry to your signal handler to the "currently blocked signals" set at entry.
(Note that the OS's automatic blocking and unblocking of signals at entry and exit to your signal handler is done with sigprocmask, using SIG_BLOCK and SIG_SETMASK—not SIG_UNBLOCK—with the mask for the SIG_SETMASK at exit set by saving the previous mask filled in via SIG_BLOCK. Well, it's normally done inside kernel code, rather than actually calling sigprocmask, but the effect is the same, just more efficient.)
Manual has said that setitimer is shared in the whole PROCESS and the SIGPROF is send to the PROCESS not to the thread.
But when I create the timer in my multithread PROCESS, unless I create independent stacks for every thread in the PROCESS to handler the signo, I will got some very serious errors in the sig handler. Through some debugging, I confirm that the stack(sole stack case) must have been reenterd.
So now I suspect that SIGPROFs may be send to multithread at the same time? Thanks!
I don't follow the details of your question but the general case is:
A signal may be generated (and thus pending) for a process as a whole (e.g., when sent using kill(2)) or for a specific thread (e.g., certain signals, such as SIGSEGV and SIGFPE, generated as a consequence of executing a specific machine-language instruction are thread directed, as are signals targeted at a specific thread using pthread_kill(3)). 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.
man (7) signal
You can block the signal for specific threads with pthread_sigmask and by elimination direct it to the thread you want to handle it.
According to POSIX, the alternate signal stack established with sigaltstack is per-thread, and is not inherited by new threads. However, I believe some versions of Linux and/or userspace pthread library code (at least old kernels with LinuxThreads and maybe some versions with NPTL too?) have a bug where the alternate stack is inherited, and of course that will lead to crashing whenever you use the alternate stack. Is there a reason you need alternate stacks? Normally the only purpose is to handle stack overflows semi-gracefully (allowing yourself some stack place to catch SIGSEGV and save any unsaved data before exiting). I would just disable it.
Alternatively, use pthread_sigmask to block SIGPROF in all threads but the main one. Note that, to avoid a nasty race condition here, you need to block it in the main thread before calling pthread_create so that the new thread starts with it blocked, and unblock it after pthread_create returns.
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.
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.