I'm a newbie in C. I want to create a program with two threads that will send signals (SIGUSR1 and SIGNUSR2) in a loop and four threads that will waiting for these signals and handle them.
I understood that sending the signal I need to do: kill(getpid,SIGUSR1); but howto I create four threads that will wait for the signal? the signal is registered to a specific function. How four threads will wait for the same signal?
Can I have other threads checking the type of signal also (without stopping the signal to reach the other threads)?
Thanks.
Update:
I'm trying to have four threads waiting for signals, when the two threads send the signals, the threads don't know which thread will catch the signal. I don't want to specify the thread id that will receive the signal.
When using pthread_kill() I need to specify the thread id (which I'm trying not to do).
Update: This answer is probably partly useless. You should use pthread_kill to send signals to a specific thread. I'll leave it around in case someone finds something in it, though.
On Linux, threads cannot be handled with kill, since kill will send the signal to any random thread that isn't blocking the signal.
Instead, you want the tgkill system call, which targets a specific thread. Which thread? You find out with the system call gettid.
Unfortunately, glibc doesn't provide wrappers for those two system calls. No problem, you can write those yourself:
#include <signal.h>
#include <sys/syscall.h>
#include <sys/types.h>
pid_t gettid()
{
return syscall(SYS_gettid);
}
int tgkill(int sig, pid_t pgid, pid_t tid)
{
return syscall(SYS_tkill, sig, pgid, tid);
}
The first argument of tgkill is the signal, as for kill. The second is the thread group id, which is the same as the process id of your process (obtainable with getpid). The last argument is the kernel thread id, which you obtain with gettid, and which also makes up the directories in /proc/<pid>/task/ on Linux.
Finally, you need to be able to wait for a signal to arrive. You do this by blocking the signal in the thread with pthread_sigmask and then using sigwaitinfo or sigtimedwait:
// block signal
sigset_t newset, oldset;
sigemptyset(&nweset);
sigaddset(&newset, SIGUSR1);
pthread_sigmask(SIG_BLOCK, &newset, &oldset);
// wait
sigwaitinfo(&newset, NULL);
// restore previous signal mask
pthread_sigmast(SIG_SETMASK, &oldset, NULL);
I really wouldn't recommend using SIGUSR signals for thread synchronization. If you want pthreads to wait on a signal, I'd look at the man pages for pthread_cond_signal
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).
I am implementing a program that uses threads. I want Each created thread to be delayed for a time. Then a signal is sent to the thread, and the handler should print a message. My issue is in sending a signal to a thread. how could it be possible to send an alarm signal to each thread created?
I can use pthread_kill(), but how could I specify the time as in alarm(6) or so on?
void *thread(void *parameter)
{
//How to send a signal to a thread
}
void threadHandler(int sig)
{
printf("hello from thread\n");
}
Well, one possibility would be to make an additional thread which sleeps for a given amount of time using e.g. usleep and then uses pthread_kill to send the signal you want to send to the correct thread. If you e.g. want to send three signals, after 1, 3 and 5 seconds have passed, you can use this code:
usleep(1*1000*1000);
pthread_kill(thread1, SIGALRM);
usleep(2*1000*1000);
pthread_kill(thread2, SIGALRM);
usleep(2*1000*1000);
pthread_kill(thread3, SIGALRM);
If you're on Linux, you can use timerfd_create() to create a timer file descriptor from which data can be read after the given amount of time has passed. So, if you have e.g. 10 threads, you can create 10 timerfds with the thread-specific timeout and then use an epoll_wait() loop (see epoll_create and epoll_wait manual pages) which listens for data to be read from the timerfds and sends the signal to the correct thread once there is data to be read.
I don't think there is any ready-made interface that sends a SIGALRM signal to a specific thread after a specific amount of time has passed, but if creating an extra thread is an option you can definitely emulate it using usleep() or timerfd_create() / epoll_wait().
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.
Is there a way to change the signal mask of a thread from another thread?
I am supposed to write a multithreaded C application that doesn't use mutex, semaphores and condition variables, only signals.
So it would look like something like this:
The main Thread sends SIGUSR1 to its process and and one of the 2 threads (not including the main thread), will respond to the signal and block SIGUSR1 from the sigmask and sleep. Then the main thread sends SIGUSR1 again, the other thread will respond, block SIGUSR1 from its sigmask, unblock SIGUSR1 from the other threads sigmask, so it will respond to SIGUSR1 again.
So essentially whenever the main thread sends SIGUSR1 the two other threads swap between each other.
Can somebody help?
You are probably looking for pthread_sigqueue(3) called from the main thread, and sigwait(3) or sigtimedwait(2) in the child thread(s).
A thread can only modify its own signal mask (via pthread_sigmask()). If you want to modify another thread's signal mask, you will have to write code yourself to ask the other thread to do it.
Signals are being sent to the process here, so kill() or sigqueue() are the functions to use. The latter will avoid coalescing multiple signals together which may happen with kill().
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.