1/* Timeout API for single-threaded programs that use blocking 2 * syscalls (read/write/send/recv/connect/accept). 3 * 4 * Copyright (C) 2017 Red Hat, Inc. 5 * 6 * Author: Stefan Hajnoczi <stefanha@redhat.com> 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License 10 * as published by the Free Software Foundation; version 2 11 * of the License. 12 */ 13 14/* Use the following pattern: 15 * 16 * timeout_begin(TIMEOUT); 17 * do { 18 * ret = accept(...); 19 * timeout_check("accept"); 20 * } while (ret < 0 && ret == EINTR); 21 * timeout_end(); 22 */ 23 24#include <stdlib.h> 25#include <stdbool.h> 26#include <unistd.h> 27#include <stdio.h> 28#include "timeout.h" 29 30static volatile bool timeout; 31 32/* SIGALRM handler function. Do not use sleep(2), alarm(2), or 33 * setitimer(2) while using this API - they may interfere with each 34 * other. 35 */ 36void sigalrm(int signo) 37{ 38 timeout = true; 39} 40 41/* Start a timeout. Call timeout_check() to verify that the timeout hasn't 42 * expired. timeout_end() must be called to stop the timeout. Timeouts cannot 43 * be nested. 44 */ 45void timeout_begin(unsigned int seconds) 46{ 47 alarm(seconds); 48} 49 50/* Exit with an error message if the timeout has expired */ 51void timeout_check(const char *operation) 52{ 53 if (timeout) { 54 fprintf(stderr, "%s timed out\n", operation); 55 exit(EXIT_FAILURE); 56 } 57} 58 59/* Stop a timeout */ 60void timeout_end(void) 61{ 62 alarm(0); 63 timeout = false; 64} 65