Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /* Timeout API for single-threaded programs that use blocking
0003  * syscalls (read/write/send/recv/connect/accept).
0004  *
0005  * Copyright (C) 2017 Red Hat, Inc.
0006  *
0007  * Author: Stefan Hajnoczi <stefanha@redhat.com>
0008  */
0009 
0010 /* Use the following pattern:
0011  *
0012  *   timeout_begin(TIMEOUT);
0013  *   do {
0014  *       ret = accept(...);
0015  *       timeout_check("accept");
0016  *   } while (ret < 0 && ret == EINTR);
0017  *   timeout_end();
0018  */
0019 
0020 #include <stdlib.h>
0021 #include <stdbool.h>
0022 #include <unistd.h>
0023 #include <stdio.h>
0024 #include "timeout.h"
0025 
0026 static volatile bool timeout;
0027 
0028 /* SIGALRM handler function.  Do not use sleep(2), alarm(2), or
0029  * setitimer(2) while using this API - they may interfere with each
0030  * other.
0031  */
0032 void sigalrm(int signo)
0033 {
0034     timeout = true;
0035 }
0036 
0037 /* Start a timeout.  Call timeout_check() to verify that the timeout hasn't
0038  * expired.  timeout_end() must be called to stop the timeout.  Timeouts cannot
0039  * be nested.
0040  */
0041 void timeout_begin(unsigned int seconds)
0042 {
0043     alarm(seconds);
0044 }
0045 
0046 /* Exit with an error message if the timeout has expired */
0047 void timeout_check(const char *operation)
0048 {
0049     if (timeout) {
0050         fprintf(stderr, "%s timed out\n", operation);
0051         exit(EXIT_FAILURE);
0052     }
0053 }
0054 
0055 /* Stop a timeout */
0056 void timeout_end(void)
0057 {
0058     alarm(0);
0059     timeout = false;
0060 }