I am developing an application wherein I have created a timer using timer_create function which upon expiration delivers a signal to a thread. As of now I am able to implement delivering a timer signal to a particular thread. The problem that I am facing now is if there is an other timer, how to deliver the signal to another separate thread(basically 1st timer signal to thread A and second timer signal to thread B). This is what I have written so far
static void *
sig_threadproc(void *thrarg)
{
sigset_t sigset;
sigemptyset(&sigset);
sigaddset(&sigset, SIGALRM);
/* endless loop to wait for and handle a signal repeatedly */
for (;;) {
int sig;
int error;
error = sigwait(&sigset, &sig);
if (error == 0) {
assert(sig == SIGALRM);
printf("got SIGALRM\n");
} else {
perror("sigwait");
}
}
return NULL;
}
static void
sig_alrm_handler(int signo)
{
/**
* dummy signal handler,
* the signal is actually handled in sig_threadproc()
**/
}
int
main(int argc, char *argv[])
{
sigset_t sigset;
struct sigaction sa;
pthread_t sig_thread;
struct itimerspec tspec;
timer_t timer_id;
/* mask SIGALRM in all threads by default */
sigemptyset(&sigset);
sigaddset(&sigset, SIGALRM);
sigprocmask(SIG_BLOCK, &sigset, NULL);
/* we need a signal handler.
* The default is to call abort() and
* setting SIG_IGN might cause the signal
* to not be delivered at all.
**/
memset(&sa, 0, sizeof(sa));
sa.sa_handler = sig_alrm_handler;
sigaction(SIGALRM, &sa, NULL);
/* create SIGALRM looper thread */
pthread_create(&sig_thread, NULL, sig_threadproc, NULL);
/* setup timer */
tspec.it_interval.tv_sec = 1;
tspec.it_interval.tv_nsec = 0;
tspec.it_value.tv_sec = 1;
tspec.it_value.tv_nsec = 0;
timer_create(CLOCK_REALTIME, NULL, &timer_id);
timer_settime(timer_id, 0, &tspec, NULL);
/**
* this might return early if usleep() is interrupted (by a signal)
* It should not happen, since SIGALRM is blocked on the
* main thread
**/
usleep(10000000);
return 0;
}
Do not use SIGALRM
for real time timer, instead use SIGRTMIN
. So you will create two timer, for the 1st one, set sigev_signo
member of sevp
argument to SIGRTMIN + 0
, and set the the 2nd one's segev_signo
to SIGRTMIN + 1
. This means the when the 1st timer fires, your process will receive SIGRTMIN
signal, when 2nd fires, you will receive SIGRTMIN + 1
.
Then call pthread_sigmask
in the 2 threads of your program, mask signal SIGRTMIN
in your thread B, and mask SIGRTMIN + 1
in your thread A.
As a result, your thread A will only be notified when 1st timer fires, and thread B will get notification from 2nd timer.