1b886d83cSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 20b025033SStefan Hajnoczi /* Timeout API for single-threaded programs that use blocking 30b025033SStefan Hajnoczi * syscalls (read/write/send/recv/connect/accept). 40b025033SStefan Hajnoczi * 50b025033SStefan Hajnoczi * Copyright (C) 2017 Red Hat, Inc. 60b025033SStefan Hajnoczi * 70b025033SStefan Hajnoczi * Author: Stefan Hajnoczi <stefanha@redhat.com> 80b025033SStefan Hajnoczi */ 90b025033SStefan Hajnoczi 100b025033SStefan Hajnoczi /* Use the following pattern: 110b025033SStefan Hajnoczi * 120b025033SStefan Hajnoczi * timeout_begin(TIMEOUT); 130b025033SStefan Hajnoczi * do { 140b025033SStefan Hajnoczi * ret = accept(...); 150b025033SStefan Hajnoczi * timeout_check("accept"); 160b025033SStefan Hajnoczi * } while (ret < 0 && ret == EINTR); 170b025033SStefan Hajnoczi * timeout_end(); 180b025033SStefan Hajnoczi */ 190b025033SStefan Hajnoczi 200b025033SStefan Hajnoczi #include <stdlib.h> 210b025033SStefan Hajnoczi #include <stdbool.h> 220b025033SStefan Hajnoczi #include <unistd.h> 230b025033SStefan Hajnoczi #include <stdio.h> 240b025033SStefan Hajnoczi #include "timeout.h" 250b025033SStefan Hajnoczi 260b025033SStefan Hajnoczi static volatile bool timeout; 270b025033SStefan Hajnoczi 280b025033SStefan Hajnoczi /* SIGALRM handler function. Do not use sleep(2), alarm(2), or 290b025033SStefan Hajnoczi * setitimer(2) while using this API - they may interfere with each 300b025033SStefan Hajnoczi * other. 310b025033SStefan Hajnoczi */ sigalrm(int signo)320b025033SStefan Hajnoczivoid sigalrm(int signo) 330b025033SStefan Hajnoczi { 340b025033SStefan Hajnoczi timeout = true; 350b025033SStefan Hajnoczi } 360b025033SStefan Hajnoczi 370b025033SStefan Hajnoczi /* Start a timeout. Call timeout_check() to verify that the timeout hasn't 380b025033SStefan Hajnoczi * expired. timeout_end() must be called to stop the timeout. Timeouts cannot 390b025033SStefan Hajnoczi * be nested. 400b025033SStefan Hajnoczi */ timeout_begin(unsigned int seconds)410b025033SStefan Hajnoczivoid timeout_begin(unsigned int seconds) 420b025033SStefan Hajnoczi { 430b025033SStefan Hajnoczi alarm(seconds); 440b025033SStefan Hajnoczi } 450b025033SStefan Hajnoczi 460b025033SStefan Hajnoczi /* Exit with an error message if the timeout has expired */ timeout_check(const char * operation)470b025033SStefan Hajnoczivoid timeout_check(const char *operation) 480b025033SStefan Hajnoczi { 490b025033SStefan Hajnoczi if (timeout) { 500b025033SStefan Hajnoczi fprintf(stderr, "%s timed out\n", operation); 510b025033SStefan Hajnoczi exit(EXIT_FAILURE); 520b025033SStefan Hajnoczi } 530b025033SStefan Hajnoczi } 540b025033SStefan Hajnoczi 550b025033SStefan Hajnoczi /* Stop a timeout */ timeout_end(void)560b025033SStefan Hajnoczivoid timeout_end(void) 570b025033SStefan Hajnoczi { 580b025033SStefan Hajnoczi alarm(0); 590b025033SStefan Hajnoczi timeout = false; 600b025033SStefan Hajnoczi } 61