3

I have a small piece of code, where i have used a POSIX timer: timer_create( ). The timer is created using the signal approach (SIGEV_SIGNAL) - as SIGEV_THREAD not supported on our platform. When the timer expires, it generates a signal, SIGUSR1, to notify of it's expiration, and there is a corresponding handler, to catch this signal, inside this handler (in actual program, not shown on code) i have a flag which sets, once the signal given by timer is caught.

Uptill this, everything is fine: Problem is, suppose if the test program also generates same signal as the timer (SIGUSR1 in this case), then the same flag is set, not by timer. So there is no way to discriminate, wether the signal received at signal handler is that of a timer, or any other test program.

Can you help me, to resolve this issue?

Thanks in advance.

enter code here
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
#include <signal.h>
#include <errno.h>
#include <string.h>


void sig_handlerTimer1(int);

time_t timerid;
int main()
{
     int i;
     static struct sigaction sa;


     static struct sigevent sevp;  // argument to timer_create
     static struct itimerspec its; // argument to timer_gettime

     memset (&sevp, 0, sizeof (struct sigevent));
     sevp.sigev_value.sival_ptr = &timerid;
     sevp.sigev_notify = SIGEV_SIGNAL;
     sevp.sigev_notify_attributes = NULL;
     sevp.sigev_signo = SIGUSR1;
     sevp.sigev_notify_function=sig_handlerTimer1;

     /* Setting timer interval */
     its.it_interval.tv_sec = 0;
     its.it_interval.tv_nsec = 0;

     /* Setting timer expiration */
     its.it_value.tv_sec = 2;  // First expiry after 1 sec
     its.it_value.tv_nsec = 0;

     /* Setting the signal handlers before invoking timer*/
     sa.sa_handler = sig_handlerTimer1;
     sa.sa_flags = 0;
     sigaction(SIGUSR1, &sa, NULL);

     if (timer_create(CLOCK_REALTIME, &sevp, &timerid) == -1)
     {
             fprintf(stderr, "LeakTracer (timer_trackStartTime): timer_create failed   to create timer. " \
                    "Leak measurement will be for entire duration of the execution   period:%s \n", strerror(errno));
            return;

      }

     if (timer_settime(timerid, 0, &its, NULL) == -1)
     {
             fprintf(stderr, "LeakTracer (timer_trackStartTime): timer_settime failed  to set the timer. " \
                    "Leak measurement will be for entire duration of execution period:%s \n", strerror(errno));
             return;

      }

      for(i=0; i<10; i++)
      {
             printf("%d\n",i);
             if(i==3) {
                 kill(getpid(), SIGUSR1); // SIGUSR1 also generated by test program  which reaches same handler and sets flag (THIS IS UN-DESIRABLE)
              }
             sleep(1);
       }

  }

  void sig_handlerTimer1(int signum)
  {

     int flag = 1;
     printf("Caught signal: %d\n",signum); // How to understand this signal caught, is that of test program of timer expiry?
     if (timer_delete(timerid) < 0)
     {
             fprintf(stderr, "timer deletion failed. " \
                     "This may result in some memory leaks (sig_handlerTimer1):%s \n", strerror(errno));
      }
   }

Added: Is there, any way to know inside the handler wether the timer has really expired or not, once signal is caught?

RajSanpui
  • 11,556
  • 32
  • 79
  • 146
  • 1
    **You** asked this before, concentrate on *that* question: http://stackoverflow.com/questions/5740954/problem-in-timers-and-signal – cnicutar Apr 27 '11 at 07:13

3 Answers3

4

You can distinguish the cause of the signal by installing the signal handler with the SA_SIGINFO flag and the sa_sigaction member of struct sigaction, then using the si_code element of the siginfo_t * passed to the signal handler. If it's SI_TIMER then the signal was generated by timer expiry.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
  • +1 for SI_TIMER. Btw if I have a long running function, thread & child process, how should I kill them in signal-safe & thread-safe manner? – Viet May 30 '12 at 03:30
  • Btw Linux man page for sigqueue says: "On Linux, the underlying system call is actually named rt_sigqueueinfo()... Inside the glibc sigqueue() wrapper, this argument, info, is initialized as follows: info.si_code = SI_QUEUE; ..." So on Linux someone can actually send rt signal with si_code equal to SI_TIMER. –  Jul 10 '12 at 13:15
0

Here is the almost same question asked, and that is being answered. In that solution he is setting pointer to sigval union, you can also set any int value. That value can be checked in the handler, if the value is same that is set by you, then it's your signal. Following is the defination of sigval union :

union sigval {
    int sival_int;
    void *sival_ptr;
}; 

you can set seg.sigev_value.sival_int = yourint and in handler check the same value by comparing this way:

if(si->si_value.sival_int == yourint)
 printf("My event");
else
 printf("It's not");

Hope this helps.

Community
  • 1
  • 1
Yuvi
  • 1,344
  • 4
  • 24
  • 46
0

You are probably going to be OK, as the only way of getting SIGUSR1 is to generate it yourself, either within the process, using the kill() system call or as a result of the timer elapsing, or from the command line using the kill command.

There is also a SIGUSR2 that you could use for any additional purpose.

trojanfoe
  • 120,358
  • 21
  • 212
  • 242
  • Imagine, if the test program generates SIGUSR1 before the timer expiry, and the `flag` is set, by that (before the timer actually sets it via expiry), and this is undesirable. How is it OK, you say? – RajSanpui Apr 27 '11 at 06:47
  • @trojanfoe: Infact, the test program linked to my tool can generate any signal, we can't restrict a user not to use SIGUSR1, same also holds for SIGUSR2. – RajSanpui Apr 27 '11 at 06:49
  • There isn't any way to distinguish what generated the signal. You need to either guarantee that `SIGUSR1` is only generated by the timer or use a different timing mechanism altogether. – trojanfoe Apr 27 '11 at 06:50
  • Is there any API of function to know wether the timer has expired or not, once i reach the handler? – RajSanpui Apr 27 '11 at 06:52
  • Also, what are the other timer mechansisms as an alternate? – RajSanpui Apr 27 '11 at 06:53
  • Not to my knowledge, no. As for alternative timers, it really depends what you are doing. If the program focuses around I/O then you can use non-blocking I/O and use `poll()` with a timeout value; you can then simply check for a timeout condition when the call returns. Otherwise you could simply check at regular intervals for the timeout condition. – trojanfoe Apr 27 '11 at 06:54
  • `Otherwise you could simply check at regular intervals for the timeout condition` can you please elaborate on this? This is a very urgent issue for us. – RajSanpui Apr 27 '11 at 07:10