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 building my own shell in C. I want to implement an builtin called alarm that takes in an integer argument for the number of seconds. The builtin just sends the user a message after i seconds (once) but the shell functionality should continue working in the meantime.
Heres what I have so far:
int seconds;
int main(int argc, char const *argv[], char* envp[]){
...
signal(SIGALRM, alarmHandler);
...
}
void alarmHandler(int sig) {
signal(sig, SIG_IGN);
alarm(seconds);
printf("%s\n", "message");
signal(SIGALRM, alarmHandler);
}
void mainProgram(char* string, char* argument){
... //built ins that don't require forking
pid_t processID = fork();
if(processID==0){ //child
if(strcmp(string, "alarm") == 0){
seconds = atoi(argument);
signal(SIGALRM, alarmHandler);
}else{ // parent
usleep(100000)
}
Clearly that doesn't work. I'm kinda lost. I've been trying this for the past couple of hours and I'm unsure of what to do.
Perhaps you've got the wrong idea of what signal does...
The signal system call can be used for setting up handling of signals. Generally speaking, use the kill system call for sending signals.
OTOH, perhaps it's the difference between BSD signal handling semantics and System V signal handling semantics that's contributing to the confusion. System V signal handling semantics can necessitate calling signal (again) within the signal handler function. Newer linux systems at least stick with the BSD signal handling semantics which are reliable and don't require signal to be called again unless you wanted to change the handler that gets invoked.
As a side note, once you get past using signal correctly, I'd recommend using sigaction instead. You can read the 'Portability' section of the signal manual page that I linked to learn more about why you should use sigaction instead of signal.
But onwards...
There are other system calls that can be used to send signals in addition to the kill system call. Like in your case you may want to use alarm or setitimer.
Alternatively, if you wanted to implement something like what alarm does (without using alarm or setitimer), you could use a separate process (via a call to fork perhaps) that calls a sleep function followed by calling kill like this:
usleep(100000);
kill(pid, SIGALRM);
In this example then, pid would be the process ID of the process that you wanted to send the SIGALRM signal to (which is the signal that alarm sends).
Hope this helps answer your question.
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
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 have a thread running in the background that is reading events from an input device in a blocking fashion, now when I exit the application I want to clean up the thread properly, but I can't just run a pthread_join() because the thread would never exit due to the blocking IO.
How do I properly solve that situation? Should I send a pthread_kill(theard, SIGIO) or a pthread_kill(theard, SIGALRM) to break the block? Is either of that even the right signal? Or is there another way to solve this situation and let that child thread exit the blocking read?
Currently a bit puzzled since none of my googling turned up a solution.
This is on Linux and using pthreads.
Edit: I played around a bit with SIGIO and SIGALRM, when I don't install a signal handler they break the blocking IO up, but give a message on the console ("I/O possible") but when I install a signal handler, to avoid that message, they no longer break the blocking IO, so the thread doesn't terminate. So I am kind of back to step one.
The canonical way to do this is with pthread_cancel, where the thread has done pthread_cleanup_push/pop to provide cleanup for any resources it is using.
Unfortunately this can NOT be used in C++ code, ever. Any C++ std lib code, or ANY try {} catch() on the calling stack at the time of pthread_cancel will potentially segvi killing your whole process.
The only workaround is to handle SIGUSR1, setting a stop flag, pthread_kill(SIGUSR1), then anywhere the thread is blocked on I/O, if you get EINTR check the stop flag before retrying the I/O. In practice, this does not always succeed on Linux, don't know why.
But in any case it's useless to talk about if you have to call any 3rd party lib, because they will most likely have a tight loop that simply restarts I/O on EINTR. Reverse engineering their file descriptor to close it won't cut it either—they could be waiting on a semaphore or other resource. In this case, it is simply impossible to write working code, period. Yes, this is utterly brain-damaged. Talk to the guys who designed C++ exceptions and pthread_cancel. Supposedly this may be fixed in some future version of C++. Good luck with that.
I too would recommend using a select or some other non-signal-based means of terminating your thread. One of the reasons we have threads is to try and get away from signal madness. That said...
Generally one uses pthread_kill() with SIGUSR1 or SIGUSR2 to send a signal to the thread. The other suggested signals--SIGTERM, SIGINT, SIGKILL--have process-wide semantics that you may not be interested in.
As for the behavior when you sent the signal, my guess is that it has to do with how you handled the signal. If you have no handler installed, the default action of that signal are applied, but in the context of the thread that received the signal. So SIGALRM, for instance, would be "handled" by your thread, but the handling would consist of terminating the process--probably not the desired behavior.
Receipt of a signal by the thread will generally break it out of a read with EINTR, unless it is truly in that uninterruptible state as mentioned in an earlier answer. But I think it's not, or your experiments with SIGALRM and SIGIO would not have terminated the process.
Is your read perhaps in some sort of a loop? If the read terminates with -1 return, then break out of that loop and exit the thread.
You can play with this very sloppy code I put together to test out my assumptions--I am a couple of timezones away from my POSIX books at the moment...
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <signal.h>
int global_gotsig = 0;
void *gotsig(int sig, siginfo_t *info, void *ucontext)
{
global_gotsig++;
return NULL;
}
void *reader(void *arg)
{
char buf[32];
int i;
int hdlsig = (int)arg;
struct sigaction sa;
sa.sa_handler = NULL;
sa.sa_sigaction = gotsig;
sa.sa_flags = SA_SIGINFO;
sigemptyset(&sa.sa_mask);
if (sigaction(hdlsig, &sa, NULL) < 0) {
perror("sigaction");
return (void *)-1;
}
i = read(fileno(stdin), buf, 32);
if (i < 0) {
perror("read");
} else {
printf("Read %d bytes\n", i);
}
return (void *)i;
}
main(int argc, char **argv)
{
pthread_t tid1;
void *ret;
int i;
int sig = SIGUSR1;
if (argc == 2) sig = atoi(argv[1]);
printf("Using sig %d\n", sig);
if (pthread_create(&tid1, NULL, reader, (void *)sig)) {
perror("pthread_create");
exit(1);
}
sleep(5);
printf("killing thread\n");
pthread_kill(tid1, sig);
i = pthread_join(tid1, &ret);
if (i < 0)
perror("pthread_join");
else
printf("thread returned %ld\n", (long)ret);
printf("Got sig? %d\n", global_gotsig);
}
Your select() could have a timeout, even if it is infrequent, in order to exit the thread gracefully on a certain condition. I know, polling sucks...
Another alternative is to have a pipe for each child and add that to the list of file descriptors being watched by the thread. Send a byte to the pipe from the parent when you want that child to exit. No polling at the cost of a pipe per thread.
Old question which could very well get a new answer as things have evolved and a new technology is now available to better handle signals in threads.
Since Linux kernel 2.6.22, the system offers a new function called signalfd() which can be used to open a file descriptor for a given set of Unix signals (outside of those that outright kill a process.)
// defined a set of signals
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGUSR1);
// ... you can add more than one ...
// prevent the default signal behavior (very important)
sigprocmask(SIG_BLOCK, &set, nullptr);
// open a file descriptor using that set of Unix signals
f_socket = signalfd(-1, &set, SFD_NONBLOCK | SFD_CLOEXEC);
Now you can use the poll() or select() functions to listen to the signal along the more usual file descriptor (socket, file on disk, etc.) you were listening on.
The NONBLOCK is important if you want a loop that can check signals and other file descriptors over and over again (i.e. it is also important on your other file descriptor).
I have such an implementation that works with (1) timers, (2) sockets, (3) pipes, (4) Unix signals, (5) regular files. Actually, really any file descriptor plus timers.
https://github.com/m2osw/snapcpp/blob/master/snapwebsites/libsnapwebsites/src/snapwebsites/snap_communicator.cpp
https://github.com/m2osw/snapcpp/blob/master/snapwebsites/libsnapwebsites/src/snapwebsites/snap_communicator.h
You may also be interested by libraries such as libevent
Depends how it's waiting for IO.
If the thread is in the "Uninterruptible IO" state (shown as "D" in top), then there really is absolutely nothing you can do about it. Threads normally only enter this state briefly, doing something such as waiting for a page to be swapped in (or demand-loaded, e.g. from mmap'd file or shared library etc), however a failure (particularly of a NFS server) could cause it to stay in that state for longer.
There is genuinely no way of escaping from this "D" state. The thread will not respond to signals (you can send them, but they will be queued).
If it's a normal IO function such as read(), write() or a waiting function like select() or poll(), signals would be delivered normally.
One solution that occurred to me the last time I had an issue like this was to create a file (eg. a pipe) that existed only for the purpose of waking up blocking threads.
The idea would be to create a file from the main loop (or 1 per thread, as timeout suggests - this would give you finer control over which threads are woken). All of the threads that are blocking on file I/O would do a select(), using the file(s) that they are trying to operate on, as well as the file created by the main loop (as a member of the read file descriptor set). This should make all of the select() calls return.
Code to handle this "event" from the main loop would need to be added to each of the threads.
If the main loop needed to wake up all of the threads it could either write to the file or close it.
I can't say for sure if this works, as a restructure meant that the need to try it vanished.
I think, as you said, the only way would be to send a signal then catch and deal with it appropriately. Alternatives might be SIGTERM, SIGUSR1, SIGQUIT, SIGHUP, SIGINT, etc.
You could also use select() on your input descriptor so that you only read when it is ready. You could use select() with a timeout of, say, one second and then check if that thread should finish.
I always add a "kill" function related to the thread function which I run before join that ensures the thread will be joinable within reasonable time. When a thread uses blocking IO I try to utilize the system to break the lock. For example, when using a socket I would have kill call shutdown(2) or close(2) on it which would cause the network stack to terminate it cleanly.
Linux' socket implementation is thread safe.
I'm surprised that nobody has suggested pthread_cancel. I recently wrote a multi-threaded I/O program and calling cancel() and the join() afterwards worked just great.
I had originally tried the pthread_kill() but ended up just terminating the entire program with the signals I tested with.
If you're blocking in a third-party library that loops on EINTR, you might want to consider a combination of using pthread_kill with a signal (USR1 etc) calling an empty function (not SIG_IGN) with actually closing/replacing the file descriptor in question. By using dup2 to replace the fd with /dev/null or similar, you'll cause the third-party library to get an end-of-file result when it retries the read.
Note that by dup()ing the original socket first, you can avoid needing to actually close the socket.
Signals and thread is a subtle problem on Linux according to the different man pages.
Do you use LinuxThreads, or NPTL (if you are on Linux) ?
I am not sure of this, but I think the signal handler affects the whole process, so either you terminate your whole process or everything continue.
You should use timed select or poll, and set a global flag to terminate your thread.
I think the cleanest approach would have the thread using conditional variables in a loop for continuing.
When an i/o event is fired, the conditional should be signaled.
The main thread could just signal the condition while chaning the loop predicate to false.
something like:
while (!_finished)
{
pthread_cond_wait(&cond);
handleio();
}
cleanup();
Remember with conditional variables to properly handle signals. They can have things such as 'spurious wakeups'. So i would wrap your own function around the cond_wait function.
struct pollfd pfd;
pfd.fd = socket;
pfd.events = POLLIN | POLLHUP | POLLERR;
pthread_lock(&lock);
while(thread_alive)
{
int ret = poll(&pfd, 1, 100);
if(ret == 1)
{
//handle IO
}
else
{
pthread_cond_timedwait(&lock, &cond, 100);
}
}
pthread_unlock(&lock);
thread_alive is a thread specific variable that can be used in combination with the signal to kill the thread.
as for the handle IO section you need to make sure that you used open with the O_NOBLOCK option, or if its a socket there is a similar flag you can set MSG_NOWAIT??. for other fds im not sure