61 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/* Timeout API for single-threaded programs that use blocking3 * syscalls (read/write/send/recv/connect/accept).4 *5 * Copyright (C) 2017 Red Hat, Inc.6 *7 * Author: Stefan Hajnoczi <stefanha@redhat.com>8 */9 10/* Use the following pattern:11 *12 * timeout_begin(TIMEOUT);13 * do {14 * ret = accept(...);15 * timeout_check("accept");16 * } while (ret < 0 && ret == EINTR);17 * timeout_end();18 */19 20#include <stdlib.h>21#include <stdbool.h>22#include <unistd.h>23#include <stdio.h>24#include "timeout.h"25 26static volatile bool timeout;27 28/* SIGALRM handler function. Do not use sleep(2), alarm(2), or29 * setitimer(2) while using this API - they may interfere with each30 * other.31 */32void sigalrm(int signo)33{34 timeout = true;35}36 37/* Start a timeout. Call timeout_check() to verify that the timeout hasn't38 * expired. timeout_end() must be called to stop the timeout. Timeouts cannot39 * be nested.40 */41void timeout_begin(unsigned int seconds)42{43 alarm(seconds);44}45 46/* Exit with an error message if the timeout has expired */47void timeout_check(const char *operation)48{49 if (timeout) {50 fprintf(stderr, "%s timed out\n", operation);51 exit(EXIT_FAILURE);52 }53}54 55/* Stop a timeout */56void timeout_end(void)57{58 alarm(0);59 timeout = false;60}61