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