timer_create() not able to catch a signal in handler function - c

Here i am trying achieve a timer say 0-10secs and an interval of 2secs each,so that i need to generate an interrupt # every 2secs(total 5 times) saying 2secs completed. which i have been cross checking in handler() function by using printf(). But i am not able to achieve the desired result.please put me touch if anyone is aware of it.
Thanks in advance.
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <time.h>
#define SIGTIMER (SIGRTMAX)
#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \
} while (0)
void handler(int sig, siginfo_t *si, void *uc)
{
printf("Caught signal %d\n", sig);
}
int
main(int argc, char *argv[])
{
timer_t timerid;
struct sigevent sev;
struct itimerspec its;
struct itimerspec oitval;
struct sigaction sa;
/* Establish handler for timer signal */
printf("Establishing handler for signal %d\n", SIGTIMER);
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = handler;
sigemptyset(&sa.sa_mask);
if (sigaction(SIGTIMER, &sa, NULL) == -1)
errExit("sigaction");
/* Create the timer */
sev.sigev_notify = SIGEV_SIGNAL;
sev.sigev_signo = SIGTIMER;
sev.sigev_value.sival_ptr = &timerid;
if (timer_create(CLOCK_REALTIME, &sev, &timerid) == 0)
{
printf("timer ID is 0x%lx\n", (long) timerid);
/* Start the timer */
its.it_value.tv_sec = 10;
its.it_value.tv_nsec =0;
its.it_interval.tv_sec = 2;
its.it_interval.tv_nsec = 0;
if (timer_settime(timerid, 0, &its, &oitval) == -1)
errExit("timer_settime");
}
else
{
errExit("timer_create");
}
return 0;
}

First of all you should properly setup timeouts:
/* Start the timer */
its.it_value.tv_sec = 2;
its.it_value.tv_nsec = 0;
its.it_interval.tv_sec = 2;
its.it_interval.tv_nsec = 0;
it_value is the duration before first triggering, and it_interval is time between all subsequent triggerings. See here. Then, you shouldn't return from main() due it leads to process exit and you won't be able to observe timer ticks. You need to block execution somehow, e.g.
while(1) sleep(INT_MAX);
After each tick sleep() returns with errno set to EINTR so it should we wrapped into loop to allow timer to go ahead. Later you can decide when to leave this loop and exit.
P.S. Using printf() from signal handler is not a good idea. You should be very carefully with what you are doing there. It would be better just to write to some global variable and immediately return. And that var may be tested immediately after sleep() giving you an idea if you should sleep again or return.

Related

Understanding output of program

I was looking at this stack exchange question: how to call a function automatically at regular intervals?
And I tried running the code in the first answer
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
void timer_handler (int signum)
{
static int count = 0;
printf ("timer expired %d times\n", ++count);
}
int main ()
{
struct sigaction sa;
struct itimerval timer;
/* Install timer_handler as the signal handler for SIGVTALRM. */
memset (&sa, 0, sizeof (sa));
sa.sa_handler = &timer_handler;
sigaction (SIGVTALRM, &sa, NULL);
/* Configure the timer to expire after 250 msec... */
timer.it_value.tv_sec = 0;
timer.it_value.tv_usec = 250000;
/* ... and every 250 msec after that. */
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_usec = 250000;
/* Start a virtual timer. It counts down whenever this process is
executing. */
setitimer (ITIMER_REAL, &timer, NULL);
/* Do busy work. */
while (1);
}
I don't understand what it is doing. It appears to print "Alarm Clock" after 2500 milliseconds, but I don't understand how that's possible since there is no print statement to that effect. How do I get it to increment the counter every 2500 milliseconds like its supposed to?
ITIMER_REAL sends SIGALRM not SIGVTALRM.
Change the signal and it'll work.
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
void timer_handler (int signum)
{
static int count = 0;
printf ("timer expired %d times\n", ++count);
}
int main ()
{
struct sigaction sa;
struct itimerval timer;
/* Install timer_handler as the signal handler for SIGVTALRM. */
memset (&sa, 0, sizeof (sa));
sa.sa_handler = &timer_handler;
sigaction (SIGALRM, &sa, NULL);
/* Configure the timer to expire after 250 msec... */
timer.it_value.tv_sec = 0;
timer.it_value.tv_usec = 250000;
/* ... and every 250 msec after that. */
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_usec = 250000;
/* Start a virtual timer. It counts down whenever this process is
executing. */
setitimer (ITIMER_REAL, &timer, NULL);
/* Do busy work. */
while (1);
}
(Generally, it's a bad idea to printf in a signal handler since printf isn't async-signal safe, but in your case it shouldn't be dangerous, because you're interrupting regular-context code that is async-signal safe (namely the busy loop). POSIX doesn't appear to guarantee this special exception, though, so to be perfectly safe, you should refrain from making any async-signal unsafe calls in signal handlers and replace the printf with a write(1, ...).)

Sigaction and SIGALRM

Hi I'm trying to learn more about signals and I wrote a simple code that supposed to just print "bye" everything the alarm signal is send. I am using sigaction to set this. However, I keep returning NULL in my error checking could someone tell me what I'm doing wrong. Thanks in Advance!
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/time.h> /* for setitimer */
#include <unistd.h> /* for pause */
#include <signal.h> /* for signal */
#define INTERVAL 500 /* number of milliseconds to go off */
/* function prototype */
void DoStuff();
int main(int argc, char *argv[]) {
struct itimerval it_val; /* for setting itimer */
struct sigaction sa;
sa.sa_handler = &DoStuff;
/* Upon SIGALRM, call DoStuff().
* Set interval timer. We want frequency in ms,
* but the setitimer call needs seconds and useconds. */
if (sigaction(SIGALRM,&sa,NULL) < 0) { /*set the signal to be enabled if this action occurs*/
perror("Unable to catch SIGALRM");
exit(1);
}
it_val.it_interval = it_val.it_value;
it_val.it_value.tv_sec = INTERVAL/1000;
it_val.it_value.tv_usec = (INTERVAL*1000) % 1000000;
it_val.it_interval = it_val.it_value;
if (setitimer(ITIMER_REAL, &it_val, NULL) == -1) { /*set the timer to send the alarm command*/
perror("error calling setitimer()");
exit(1);
}
while(1)
{
pause();
}
}
void DoStuff() {
printf("bye\n");
}
sigaction cannot return null, since it returns an integer. I'm assuming it's returning -1. You're not correctly initializing the sigaction structure. It has many fields, but you're allowing them to be undefined. Fix the structure definition and try again. See:
http://man7.org/linux/man-pages/man2/sigaction.2.html

Timer freezes after some time

I am running the following program which implements a timer. When a thread awake after receiving a signal on condition variable from the previous running thread, it creates a timer and send a signal to the next thread on timer expiration. I want it to run for some time, but the timer stops ticking after some runs.
//Import
#define _POSIX_C_SOURCE 199309
#include <sched.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <time.h>
#include <sys/time.h>
#include <signal.h>
#include <errno.h>
#define NUM_THREADS 10
#define CLOCKID CLOCK_REALTIME
#define SIG SIGUSR1
timer_t timerid;
pthread_cond_t condA[NUM_THREADS+1] = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_t tid[NUM_THREADS];
int state = 0;
static void handler(int sig, siginfo_t *si, void *uc)
{
if(si->si_value.sival_ptr != &timerid){
printf("Stray signal\n");
} else {
//printf("Caught signal %d from timer\n", sig);
}
pthread_cond_signal(&condA[state]);
}
void *threadA(void *data_)
{
int i = 0, s;
long int loopNum, j;
int turn = (intptr_t)data_;
struct timeval tval_result;
// Timer's part starts
struct sigevent sev;
struct itimerspec its;
long long freq_nanosecs;
sigset_t mask;
struct sigaction sa;
// TImer'spart ends
while(1)
{
/* Wait for state A */
pthread_mutex_lock(&mutex);
for (;state != turn;)
{
s = pthread_cond_wait(&condA[turn], &mutex);
if (s != 0)
perror("pthread_cond_wait");
// printf("main(): state = %d\n", state);
}
pthread_mutex_unlock(&mutex);
//do stuff
for(j=0;j<10000;j++)
{//some dummy time consuming works}
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = handler;
sigemptyset(&sa.sa_mask);
sigaction(SIG, &sa, NULL);
sev.sigev_notify = SIGEV_SIGNAL;
sev.sigev_signo = SIG;
sev.sigev_value.sival_ptr = &timerid;
timer_create(CLOCKID, &sev, &timerid);
/* Start the timer */
its.it_value.tv_sec = 0;
its.it_value.tv_nsec = 2000;
its.it_interval.tv_sec = 0;
its.it_interval.tv_nsec = 0;
timer_settime(timerid, 0, &its, NULL);
pthread_mutex_lock(&mutex);
state = (state +1)%NUM_THREADS;
//pthread_cond_signal(&condA[state]);
pthread_mutex_unlock(&mutex);
// Timer's code ends
}
}
int main(int argc, char *argv[])
{
int data = 0;
int err;
while(data < NUM_THREADS)
{
//create our threads
err = pthread_create(&tid[data], NULL, threadA, (void *)(intptr_t)data);
if(err != 0)
printf("\ncan't create thread :[%s]", strerror(err));
else
// printf("\n Thread created successfully\n");
data++;
}
pthread_exit(NULL);
}
Although no printf statements are executing, why is it freezing after some time?
If no. of timers are limited, what other strategy should I use to redress this issue?
POSIX says:
It is not safe to use the pthread_cond_signal() function in a signal handler that is invoked asynchronously.
Most likely you end up corrupting the state of pthread_cond_wait/pthread_cond_signal and anything can happen.
Don't mix threads and signal handlers, it leads only to madness. There are very few things you're allowed to do inside a signal handler, even fewer that are thread related, it's very hard to ensure that the right thread ends up handling the right signal, etc.
If you're doing threads anyway implement a timer in one thread that calculates how much time it needs to sleep to deliver the next event (don't just hardcode it to your timer period since that will make your timer drift), sleep that much and call pthread_cond_signal.
Also, it's bad form to have naked pthread_cond_signal calls and most often a bug. You might get unlucky and call it just before the other thread does the pthread_cond_wait and your signal will get lost. The normal thing to do is to set a variable (protected by a mutex, that's why pthread_cond_signal wants a mutex) and then signal that the variable is set.
If you think this is too much work, condition variables are probably not the right mechanism in this case and you should use semaphores instead. Incidentally sem_post is legal to call from a signal handler according to POSIX, but I still think it's a bad idea to mix threads with signals.

Signal Handler in a separate pthread using timer_create

I am developing a small application where in I want to call a function every 1 second. This is how I implemented
Timerspec.it_interval.tv_sec=1;
Timerspec.it_interval.tv_nsec=0;
Timerspec.it_value.tv_sec=1;
Timerspec.it_value.tv_nsec=0;
timer_t timerId;
struct sigaction sa;
sa.sa_handler=&TimerFn;
sa.sa_flags=0;
sigemptyset(&sa.sa_mask);
sigaction(SIGALRM,&sa,NULL);
timer_create(CLOCK_REALTIME,NULL,&timerId);
timer_settime(timerId,0,(const itimerspec*)Timerspec,NULL);
But I want to run the TimerFn function in a separate pthread(basically a timer for pthread function). Can somebody please tell how to do this?
If you can accept the creation of a new thread for every timer tick, you can use SIGEV_THREAD:
struct sigevent evp;
memset((void *)&evp, 0, sizeof(evp));
evp.sigev_notify = SIGEV_THREAD;
evp.sigev_notify_function = &sig_alrm_handler;
evp.sigev_signo = SIGALRM;
evp.sigev_value.sigval_ptr = (void *)this;
int ret = timer_create(CLOCK_REALTIME, &evp, &_timerId);
This will create a new thread for every tick.
If you need to handle the signal in a specific thread, a little more work is required:
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;
}
You might get away with selectively unblocking SIGARLM only in the signal handler thread, causing it the only thread to be eligible to handle that signal, but that may not be portable across systems.
Other versions (including use of pthread_cond_signal()) are already discussed in this answer.
If you just want to call a function every second, here's a simple solution:
#include <pthread.h>
#include <unistd.h>
void TimerFn(void)
{
...
}
void* timer(void* arg)
{
for (;;) {
TimerFn();
sleep(1);
}
return NULL;
}
...
pthread_t timerThread;
pthread_create(&timerThread, NULL, timer, NULL);
Is there some reason this wouldn't suffice?

Is it possible to use both custom sigaction signal handler and pthread_sigmask?

I am implementing a simple timer that throws a RT signal upon expiration. What I want to do is to register a signal handler (using sigaction) that gets called when the signal occurs. Meanwhile the main code waits until the signal is called using sigwaitinfo.
Implementing either a signal handler or sigwaitinfo exclusively works fine. However when both are used, the signal handler is never called. I tried switching the order; i.e. registering the handler before blocking the signal. Makes no difference.
Here is the code
// gcc -Wall -o sigwait_example sigwait_example.c -lrt
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <time.h>
#include <errno.h>
#include <string.h>
#define install_handler(sig,sa) if( sigaction(sig, &sa, NULL) == -1 ){ \
perror("sigaction"); }
#define SIG SIGRTMIN+1
volatile int flag=0;
void handler(int signum){
flag++;
}
int main(void){
struct itimerspec its;
sigset_t blocked;
siginfo_t si;
timer_t timerid;
struct sigevent evt;
struct sigaction sa;
evt.sigev_notify = SIGEV_SIGNAL;
evt.sigev_signo = SIG;
evt.sigev_value.sival_ptr = &timerid;
if ( timer_create(CLOCK_REALTIME, &evt, &timerid) ){
perror("timer_create");
}
//setup timer
its.it_value.tv_sec = 0;
its.it_value.tv_nsec = 0.1*1E9;
its.it_interval.tv_sec = 0;
its.it_interval.tv_nsec = 0;
//arm the timer
if ( timer_settime(timerid, 0, &its, NULL) )
perror("timer_settime");
sigemptyset(&blocked);
sigaddset(&blocked, SIG);
//add SIG to blocked signals
pthread_sigmask(SIG_BLOCK, &blocked, NULL);
sa.sa_flags = SA_SIGINFO; //use this flag to set custom handler
sa.sa_sigaction = handler;
sigemptyset(&sa.sa_mask);
install_handler(SIG,sa);
while ( sigwaitinfo(&blocked, &si) == -1 && errno == EINTR );
printf("received signal: %s, flag=%d\n",strsignal(si.si_signo),flag);
//while(flag==0) sleep(1); //use this when only signal handler is used
timer_delete(timerid);
return 0;
}
I am doing this mostly for educational purposes, since I need to learn as much as possible about how threads are sent/blocked as I will be using them in threads.
It's not possible because sigwaitinfo() removes the signal from the queue.
You can, however, use sigaction(SIG, NULL, &sa) to retrieve the sigaction struct of this signal and execute the handler.

Resources