Use a system timer as a watchdog

A high-level application can use a system timer as a watchdog to cause the OS to terminate and restart that application if it becomes unresponsive. When the watchdog expires, it raises a signal that the application doesn't handle, which in turn causes the OS to terminate the application. After termination, the OS automatically restarts the application.

To use a watchdog timer:

  • Define the timer
  • Create and arm the timer
  • Reset the timer regularly before it expires

To define the timer, create an itimerspec structure and set the interval and initial expiration to a fixed value, such as one second.

#include <time.h>

const struct itimerspec watchdogInterval = { { 1, 0 },{ 1, 0 } };
timer_t watchdogTimer;

Set a notification event, signal, and signal value for the watchdog, call timer_create to create it, and call timer_settime to arm it. In this example, watchdogTimer raises the SIGALRM event. The application doesn't handle the event, so the OS terminates the application.

void SetupWatchdog(void)
{
    struct sigevent alarmEvent;
    alarmEvent.sigev_notify = SIGEV_SIGNAL;
    alarmEvent.sigev_signo = SIGALRM;
    alarmEvent.sigev_value.sival_ptr = &watchdogTimer;

    int result = timer_create(CLOCK_MONOTONIC, &alarmEvent, &watchdogTimer);
    result = timer_settime(watchdogTimer, 0, &watchdogInterval, NULL);
}

Elsewhere in the application code, reset the watchdog periodically. One technique is to use a second timer, which has a period shorter than the watchdogInterval, to verify that the application is operating as expected and, if so, reset the watchdog timer.

// Must be called periodically
void ExtendWatchdogExpiry(void)
{
    //check that application is operating normally
    //if so, reset the watchdog
    timer_settime(watchdogTimer, 0, &watchdogInterval, NULL);
}