santosh dk santosh dk - 4 months ago 21
Linux Question

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

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;
}

Answer

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.

Comments