sigsuspend is a function that changes the mask and suspends the process until a new signal is delivered, but what surprised me is that the pending signals are being delivered also after the sigsuspend.
For example:
while the process is sleeping (5 sec), a ctrl-z will not execute the SIGTSTP handler because it's masked, but after the sigsuspend the signal is received automatically
so the sigsuspend executes the pending signal handler also, it's right?
`
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
void handlerSIGTSTP()
{
printf("I have recieved the signal \n");
}
int main()
{
sigset_t mask;
sigset_t ancien;
signal(SIGTSTP,handlerSIGTSTP);
sigaddset(&mask,SIGTSTP);
sigprocmask(SIG_SETMASK,&mask,&ancien);
printf("J'entre en sleep\n");
sleep(5);
printf("J'entre en suspend\n");
sigsuspend(&ancien);
}
Execution:
J'entre en sleep
^ZJ'entre en suspend
J'ai recu le signal maintenant
Although your example code has some issues that are addressed in comments, I'll focus in this answer on the main questions you raise, which are not fundamentally dependent on the example program.
sigsuspend is a function that changes the mask and suspends the process until a new signal is delivered,
Your use of the word "new" in that description suggests a misunderstanding. The docs do not use it, and it doesn't really make sense in context.
but what surprised me is that the pending signals are being delivered also after the sigsuspend.
Yes. sigsuspend() temporarily replaces the signal mask and suspends execution until a signal is delivered whose action is to invoke a signal handler or terminate the process. That can be a signal that was already pending before sigsuspend() was called. That is one of the circumstances that the idiomatic combination of sigprocmask() with sigsuspend() is specifically aimed at handling. This allows a process to avoid handling an expected signal before it is ready for it.
For example: while the process is sleeping (5 sec), a ctrl-z will not
execute the SIGTSTP handler because it's masked, but after the
sigsuspend the signal is received automatically so the sigsuspend
executes the pending signal handler also, it's right?
Yes. In your example code, sigsuspend() unblocks SIGTSTP, so if there is a pending SIGTSTP then it is delivered within the scope of the sigsuspend(). That triggers a signal handler in your case, so when the handler returns, sigsuspend() terminates.
Related
Come to think of it, I guess the signal is sent to the OS and the program will proceed, even if the signal is still pending on the OS side. Can someone confirm?
kill(this_process, signum);
printf("will line this run in any reality of the multi-verse?");
printf("or should I go to sleep?");
sleep(10);
From the POSIX specification of kill()
If the value of pid causes sig to be generated for the sending process, and if sig is not blocked for the calling thread and if no other thread has sig unblocked or is waiting in a sigwait() function for sig, either sig or at least one pending unblocked signal shall be delivered to the sending thread before kill() returns.
So if there are no other signals pending for the process when you call kill(), the signal you send has to be delivered immediately. But if there are other signals pending, this signal could be queued and an earlier signal delivered immediately.
The pause() function blocks until a signal arrives.
Assuming the process got a signal and pause() returned, does the signal handler will be executed before the code that follows the pause() call, or the result is unexpected?
Example:
void sigusr1_handler()
{
// .. handler code
}
void main()
{
// .. bind handler to SIGUSR1
pause(); // wait for SIGUSR1
// some more code
}
Does "some more code" will always be executed after sigusr1_handler() has finished, or there is a race condition? If so, what is the solution?
I cannot think of anything besides busy-waiting, but then the pause won't be needed at all..
Citing from the man page for pause(2):
pause() returns only when a signal was caught and the signal-catching function returned. In this case, pause() returns -1, and errno is set to EINTR.
You can be sure that your signal handler runs before some more code.
Signal handlers do not run concurrently; they interrupt the thread that handles them, and the interrupted flow only continues when the signal handler returns.
However, there may be other race conditions associated with your example; with just sparse pseudo-code and not a full explanation of your usage case, it's hard to say. For example a different signal might arrive and interrupt the pause before your signal does, and then your handler could end up running later than you expected.
There are several "right ways" to do this instead:
write a single byte to a pipe in the signal handler, and read from it in the main flow of execution.
sem_post a semaphore from the signal handler, and sem_wait in the main flow of execution.
Use sigwaitinfo or sigtimedwait instead of a signal handler.
Still use pause, but in a loop:
while(!signal_handler_finished) pause();
where signal_handler_finished has type volatile sig_atomic_t, and is set to a nonzero value in the signal handler.
I'm wondering if sigaction will create a signal handler for the calling thread or the whole process. If it unblocks a signal and creates a signal handler for the entire process, then how can I make sure only a single thread will use the signal handler and have other threads block the signal.
In my case, I want a single thread to call a signal handler when an alarm signal goes off and the other threads to simply block it.
void alarmSigHandler(int signo){
}
void* alarm_thread_start_routine(void *arg){
// Perform some tasks
}
int main(){
// Main thread start
/* Unblock alarm signal */
/* Assign signal handler for alarm signal */
/* Launch alarm signal handler thread */
/* Block alarm signal with pthread_sigmask */
/* Do something */
return 0;
}
http://vip.cs.utsa.edu/classes/cs3733f2013/notes/SignalsAndThreads.html
If a signal is sent to a threaded program, any of the threads can handle the signal.
Each thread inherits the process signal mask, but each thread has its own signal mask that can be modified with pthread_sigmask.
sigprocmask should not be used in a threaded environment, but it can be used before the threads are created.
The simplest way to handle signals in a multithreaded environment is to have a thread dedicated to signal handling.
Issues involving signal safety can be handled by using sigwait:
The main process blocks all signals before creating any threads.
No signal handlers are set up.
A thread is created to handle the signals.
That thread sets up a sigset_t containing the signals of interest.
It loops, calling sigwait and handles the pending signals.
You say:
In my case, I want a single thread to call a signal handler when an alarm signal goes off and the other threads to simply block it.
Try this:
void *alrm_thread(void *arg) {
// install SIGALRM handler
// unblock SIGALRM
... do stuff ...
}
int main(int argc, char **argv) {
// block SIGALRM
// spawn alarm_thread
... do stuff or spawn other threads ..
}
SIGALRM will only be delivered to the "alrm_thread" above.
UPDATE
(Adapting Alex Che's apt comments)
This works because each thread has its own signal mask inherited from the thread which creates it.
Masking (blocking) SIGALRM in main() right away ensures all subsequent threads begin life with SIGALRM blocked. Our special thread installs the handler and unblocks SIGALRM. Since this special thread is the only thread able to receive an ALRM, it will be the thread that runs the handler.
(Now, there are some signal nuances just around the corner. Handlers or signal dispositions are process-global attributes shared by all threads. Signals can be process-directed or thread-directed. However, for your case, which is a very common case, the above is suitable.)
From the man page for signals:
The signal disposition is a per-process attribute: in a multithreaded
application, the disposition of a particular signal is the same for
all threads.
So yes, when you set a signal handler it will handle signals sent to the process; signals aren't sent to each thread individually, it is sent to any one of the threads that aren't blocking the specific message being sent.
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 simple program under Linux which sends SIGUSR1 signal to its child process in a cycle. But when I send e.g. 10 signals, sometimes happens, that the child received only 3 of them. Last sent signal is always SIGUSR2 and that is received every time.
Are the signals queuing, or when process didn't process the previous, it is simply overwritten? Is there a way I can send signals in a queue?
What happens is the following:
First signal received, namely SIGUSR1, handler is called and is running
Second signal received, since handler from nr1 is still running, the signal nr2 gets pending and blocked.
Third signal received, since handler from nr1 is still running, the signal 3 gets discarded.
Fourth, fifth...etc signal of the same type as the signal nr1 are discarded.
Once signal handler is done with signal nr1, it will process signal nr2, and then signal handler will process the SIGUSR2.
Basically, pending signals of the same type are not queued, but discarded. And no, there is no easy way to "burst" send signals that way. One always assumes that there can be several signals that are discarded, and tries to let the handler do the work of cleaning and finding out what to do (such as reaping children, if all children die at the same time).
If multiple signals of the same type are sent and not handled, they aren't queued. Say the program masks SIGUSR1, calls kill(getpid(), SIGUSR1) 10 times and unmasks SIGUSR1. It will receive SIGUSR1 just once.
Your problem is probably that SIGUSR2 is a signal that is delivered right away, while other signals are blocked or queued (in status pending).
Here's how you can check for pending signals: http://www.gnu.org/s/libc/manual/html_node/Checking-for-Pending-Signals.html
So doing simultaneous I/O of many files with SIGIO seems possible only if one uses flag SA_NODEFER for struct sigaction sa_flags field and never blocks signals.
So then, one could get interrupt from inside a signal handler and create new thread for each individual signal being handled. That gets complicated :) So no wonder why no one seems to use SIGIO.