0

I want to call timer_handler function at every 2 seconds regardless of execution time of timer_handler function here is my code

#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/time.h>

void timer_handler (int signum)
{
 static int count = 0;
 sleep(1);
 printf ("timer expired %d times %d signum \n", ++count, signum);
}

int main ()
{
 struct sigaction sa;
 struct itimerval timer;

 /* 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 2000 msec... */
 timer.it_value.tv_sec = 2;
 timer.it_value.tv_usec = 0;
 /* ... and every 2000 msec after that. */
 timer.it_interval.tv_sec = 2;
 timer.it_interval.tv_usec = 0;
 /* Start a virtual timer. It counts down whenever this process is
   executing. */
 setitimer (ITIMER_VIRTUAL, &timer, NULL);
 /* Do busy work. */
 while (1);
}

As per above code it should print timer expired 1 times 26 signum at every two second but its prints on every 3 seconds which includes sleep time so i want to call that function on every 2 seconds. I don't know where i am doing wrong If any other library is able to do this please let me know Thank you

alk
  • 69,737
  • 10
  • 105
  • 255
Krunal Sonparate
  • 1,122
  • 10
  • 29
  • 2
    there is a long list of functions that are NOT safe to use in signal handlers, both `sleep()` and `printf()` are on that list. – user3629249 Dec 28 '17 at 13:33
  • What about deleting the `sleep()`? What is your ultimate goal with this? I mean that `while (1)` is pretty wasteful. – meaning-matters Dec 28 '17 at 13:34
  • @user3629249: As [per POSIX](http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_04_03) `sleep()` *shall be* async-signal-safe. – alk Dec 28 '17 at 13:41
  • @alk, here is an excerpt from the MAN page for `sleep()` ┌──────────┬───────────────┬─────────────────────────────┐ │Interface │ Attribute │ Value │ ├──────────┼───────────────┼─────────────────────────────┤ │sleep() │ Thread safety │ MT-Unsafe sig:SIGCHLD/linux │ └──────────┴───────────────┴─────────────────────────────┘ Note the part "Unsafe sig:SIGCHLD/linux" – user3629249 Dec 28 '17 at 14:33
  • @user3629249: This man-page your are quoting documents which C implementation? – alk Dec 28 '17 at 14:35
  • @alk, here is the version of 'gcc' "gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.5) " All the man pages, etc are up to data – user3629249 Dec 29 '17 at 22:38

2 Answers2

2

Why not use wall-clock time?

To do so

  • install the signal handler for SIGALRM instead of SIGVTALRM and
  • specify ITIMER_REAL instead of ITIMER_VIRTUAL.

Unrelated but important: Signal handlers may only call async-signal-safe functions. printf() is not one of those. For a list of the latter click here and scroll down.

alk
  • 69,737
  • 10
  • 105
  • 255
  • Thank you for your response it is helpful for me. Now I want some more features in it. I want to change interval time dynamically after calling setitimer so how i can i do it – Krunal Sonparate Dec 29 '17 at 07:25
0

the call, in the signal handler: sleep(1) is adding an extra second to the processing of the signal. This extra second is not part of the execution time of the process.

remove from the signal handler:

sleep(1);

regarding:

setitimer (ITIMER_VIRTUAL, &timer, NULL);

since you want to see the signal handler executed every 2 seconds, the proper timer to use is: ITIMER_REAL not ITIMER_VIRTUAL. This will result in the 'clock on the wall' time being measured rather than the 'process run' time being measured.

Strongly suggest having the signal handler ONLY set a flag. Then the 'do nothing' loop in the main function be checking that flag, reset the flag, then call printf()` To properly accomplish this, with out an 'race' conditions, use a mutex/ Both the main and the signal handler would lock the mutex, modify the flag, then unlock the mutex.

user3629249
  • 16,402
  • 1
  • 16
  • 17