xref: /openbmc/linux/tools/testing/vsock/timeout.c (revision b886d83c)
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 Hajnoczi void 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 Hajnoczi void 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 Hajnoczi void 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 Hajnoczi void timeout_end(void)
570b025033SStefan Hajnoczi {
580b025033SStefan Hajnoczi 	alarm(0);
590b025033SStefan Hajnoczi 	timeout = false;
600b025033SStefan Hajnoczi }
61