clinuxtimerperiodic-task

Linux periodic C timers without using signal callback


Requirement is simple - Implement a C periodic timer, which can fire every say x seconds and a timer callback function should be called everytime that timer expires. Seems a simple enough question and I have browsed the web, but I am finding examples which either have FD and poll involved, or the timer callback is implemented using SIGNAL handler. I want to avoid both. Can you please share some code examples

https://man7.org/linux/man-pages/man2/timer_create.2.html - uses signals, which is not of interest to me as in my processes, there may be other reasons this SIGNAL can be called , how can I differentiate in the SIG-handler, that this signal is for my timer and not other events ?


Solution

  • how can I differentiate in the SIG-handler, that this signal is for my timer and not other events ?

    Check out the sigevent(7) man page linked from timer_create(2). One of the members of the struct sigevent that you pass to timer_create is union sigval sigev_value. This union isn't defined in the man page, but POSIX explains that it's simply

    union sigval {
        int    sival_int;  // integer signal value
        void*  sival_ptr;  // pointer signal value
    };
    

    Whatever you set here will be passed to your signal handler as the si_value member of its siginfo_t * second argument, provided you use SA_SIGINFO when calling sigaction. So you just need to use different values here as you set up timers corresponding to different callbacks. You could use sival_int for an integer ID of your own choosing that uniquely identifies this particular timer from all others, or sival_ptr for a pointer to a function or some more elaborate data structure that tells you how to handle the timer tick. Then your signal handler just needs to inspect this argument and dispatch to the callback it specifies.

    You might also consider the SIGEV_THREAD mode of timer_create, which fires off a new thread with the handler instead of raising a signal. So if you want your callback to run in its own thread, that could be a simpler route to take, as you don't need the signal handler to act as dispatcher.

    But if you don't want additional threads, I don't think there is any way to avoid working with signals. They're about the only mechanism that Unix provides for running code asynchronously.

    Do be mindful of the many restrictions on what can be done from within a signal handler; in particular, practically the entire standard C library is off limits. As such, your "asynchronous" callbacks may not be able to do much except set a flag to tell your main event loop to do the real work at some later time. So you may not gain much over a synchronous poll-type model anyway.