Search code examples
ctimetimer

sys/time.h timer only runs once


I am trying to implement a timer that continuously counts certain amount of time while the software is running. I wrote a dirty code to try how sys/time.h works.
My understanding is that if I set my it_interval struct to a non-zero value, then the timer should start counting again once it's done counting for the value stored in it_value struct.
However, my code stalls. Could someone tell me what I am missing in my code please? Also, I am using Linux.

#include <sys/time.h>
#include <stdio.h>
#include <stdint.h>

int main(void) {
    struct itimerval timer1;

    timer1.it_interval.tv_sec = 5;
    timer1.it_interval.tv_usec = 0;
    timer1.it_value.tv_sec = 5;
    timer1.it_value.tv_usec = 0 ;
    setitimer(ITIMER_REAL, &timer1, NULL);
    printf( "init interval counter: %ld.%ld\n", timer1.it_interval.tv_sec, 
    timer1.it_interval.tv_usec);
    printf( "init value counter: %ld.%ld\n\n", timer1.it_value.tv_sec, 
    timer1.it_value.tv_usec );

    while(1) {
        for (int i = 0; i < 100000000000000; i++){
            getitimer(ITIMER_REAL, &timer1);
            printf( "end interval counter: %ld.%ld\n", 
            timer1.it_interval.tv_sec, timer1.it_interval.tv_usec);
            printf( "end value counter: %ld.%ld\n\n", 
            timer1.it_value.tv_sec, timer1.it_value.tv_usec );
        }
    }
    return 0;
}

My output (shortened of course) is:
end interval counter: 5.0
end value counter: 0.8821

end interval counter: 5.0Alarm clock

Process returned 142 (0x8E) execution time: 5.033 s

Thank you in advance for your help!


Solution

  • setitimer(ITIMER_REAL,...) causes SIGALRM to be sent to the calling process upon timer expiry. SIGALRM is a normally deadly signal, whose default disposition is to kill the process.

    If you want to prevent your process from being killed by this signal, you need to handle it somehow.

    Example (prints EXPIRED from the handler every 100ms) based on your code:

    #include <sys/time.h>
    #include <stdio.h>
    #include <stdint.h>
    #include <signal.h>
    #include <unistd.h>
    void handler(int Sig)
    {
        (void)Sig;
        char msg[]="EXPIRED\n";
        ssize_t nwr = write(1,msg,sizeof(msg)-1); (void)nwr;
    }
    int main(void) {
        struct itimerval timer1;
        struct sigaction sa;
        sa.sa_handler = handler;
        sa.sa_flags = 0;
        sigemptyset(&sa.sa_mask);
        sigaction(SIGALRM,&sa,0);
    
        timer1.it_interval.tv_sec = 0;
        timer1.it_interval.tv_usec = 100000;
        timer1.it_value.tv_sec = 0;
        timer1.it_value.tv_usec = 100000 ;
        setitimer(ITIMER_REAL, &timer1, NULL);
        printf( "init interval counter: %ld.%ld\n", timer1.it_interval.tv_sec, 
        timer1.it_interval.tv_usec);
        printf( "init value counter: %ld.%ld\n\n", timer1.it_value.tv_sec, 
        timer1.it_value.tv_usec );
    
        while(1) pause();
        return 0;
    }