Signal Handler to stop Timer in C

狂风中的少年 提交于 2019-12-10 20:22:26

问题


I am trying to have a signal handler stop a timer without exiting my program. How should I go about. I want StopTimer to handle the signal to stop the timer

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

#define INTERVAL 2      // number of seconds to go off

int main(int argc, char* argv[]) {

TimerSet(INTERVAL);

while(1)
{
    // do stuff
}
return 0;
}

void TimerSet(int interval)
{
printf("starting timer\n");
struct itimerval it_val;

// interval value
it_val.it_value.tv_sec = interval;
it_val.it_interval = it_val.it_value;

// on SIGALRM, close window
if (signal(SIGALRM, TimerStop) == SIG_ERR)
{
    perror("Unable to catch SIGALRM");
    exit(1);
}

// set interval timer, returns SIGALRM on expiration
if (setitimer(ITIMER_REAL, &it_val, NULL) == -1)
{
    perror("error calling setitimer()");
    exit(1);
}
}

void TimerStop(int signum)
{
printf("Timer ran out! Stopping timer\n");
exit(signum);
}

I tried to set the setitimer interval to 0, but I am not sure how to use the same timer within the TimerStop signal handler function


回答1:


Just set it_interval to zero, and you'll get a one-shot timer. You don't need to do anything with it in your handler.

For instance, with this:

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

#define INTERVAL 2              // number of seconds to go off

void TimerStop(int signum) {
    printf("Timer ran out! Stopping timer\n");
}

void TimerSet(int interval) {
    printf("starting timer\n");
    struct itimerval it_val;

    it_val.it_value.tv_sec = interval;
    it_val.it_value.tv_usec = 0;
    it_val.it_interval.tv_sec = 0;
    it_val.it_interval.tv_usec = 0;

    if (signal(SIGALRM, TimerStop) == SIG_ERR) {
        perror("Unable to catch SIGALRM");
        exit(1);
    }
    if (setitimer(ITIMER_REAL, &it_val, NULL) == -1) {
        perror("error calling setitimer()");
        exit(1);
    }
}

int main(int argc, char *argv[]) {

    TimerSet(INTERVAL);

    while (1) {
        // do stuff
    }
    return 0;
}

the message "Timer ran out! Stopping timer" will appear only once, and your timer will stop without you doing anything.

Note that you need to fill in the tv_usec members of your struct itimerval, which your current code does not do. If you don't, it_interval is highly unlikely to be zero, and your timer will never stop.

printf(), along with the other standard IO functions, is not really safe to call from a signal handler, although in this particular case it won't cause you any problems, since the main code is just sitting in a loop and not doing anything.

Also, presume you're calling signal() on purpose - sigaction() is the recommended way for setting handlers. setitimer() is also obsolete, now, and timer_settime() is recommended.




回答2:


According to manual:

   Timers  decrement  from  it_value  to zero, generate a signal, and reset to
   it_interval.  A timer which is set to zero (it_value is zero or  the  timer
   expires and it_interval is zero) stops.

   Both  tv_sec  and  tv_usec are significant in determining the duration of a
   timer.

So timer can be set to run only once if interval is set to zero before setitimer() call (thanks to Duck's comment).



来源:https://stackoverflow.com/questions/19758101/signal-handler-to-stop-timer-in-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!