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 30 static 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 */ 36 void 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 */ 45 void timeout_begin(unsigned int seconds) 46 { 47 alarm(seconds); 48 } 49 50 /* Exit with an error message if the timeout has expired */ 51 void 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 */ 60 void timeout_end(void) 61 { 62 alarm(0); 63 timeout = false; 64 } 65