int setup_watchdog(struct tevent_context *ev, int interval) { struct sigevent sev; struct itimerspec its; struct tevent_fd *tfd; int signum = SIGRTMIN; int ret; memset(&sev, 0, sizeof(sev)); CatchSignal(signum, watchdog_handler); sev.sigev_notify = SIGEV_SIGNAL; sev.sigev_signo = signum; sev.sigev_value.sival_ptr = &watchdog_ctx.timerid; errno = 0; ret = timer_create(CLOCK_MONOTONIC, &sev, &watchdog_ctx.timerid); if (ret == -1) { ret = errno; DEBUG(SSSDBG_FATAL_FAILURE, "Failed to create watchdog timer (%d) [%s]\n", ret, strerror(ret)); return ret; } if (interval == 0) { interval = WATCHDOG_DEF_INTERVAL; } watchdog_ctx.interval.tv_sec = interval; watchdog_ctx.interval.tv_usec = 0; watchdog_ctx.ev = ev; watchdog_ctx.input_interval = interval; watchdog_ctx.timestamp = time(NULL); ret = pipe(watchdog_ctx.pipefd); if (ret == -1) { ret = errno; DEBUG(SSSDBG_FATAL_FAILURE, "pipe failed [%d] [%s].\n", ret, strerror(ret)); return ret; } sss_fd_nonblocking(watchdog_ctx.pipefd[0]); sss_fd_nonblocking(watchdog_ctx.pipefd[1]); tfd = tevent_add_fd(ev, (TALLOC_CTX *)ev, watchdog_ctx.pipefd[0], TEVENT_FD_READ, watchdog_fd_read_handler, NULL); watchdog_ctx.tfd = tfd; /* Start the timer */ /* we give 1 second head start to the watchdog event */ its.it_value.tv_sec = interval + 1; its.it_value.tv_nsec = 0; its.it_interval.tv_sec = interval; its.it_interval.tv_nsec = 0; errno = 0; ret = timer_settime(watchdog_ctx.timerid, 0, &its, NULL); if (ret == -1) { ret = errno; DEBUG(SSSDBG_FATAL_FAILURE, "Failed to create watchdog timer (%d) [%s]\n", ret, strerror(ret)); return ret; } /* Add the watchdog event and make it fire as fast as the timer */ watchdog_event_handler(ev, NULL, tevent_timeval_zero(), NULL); return EOK; }