| 1 | |
| 2 | |
| 3 | * syscalls (read/write/send/recv/connect/accept).
|
| 4 | *
|
| 5 | * Copyright (C) 2017 Red Hat, Inc.
|
| 6 | *
|
| 7 | * Author: Stefan Hajnoczi <[email protected]>
|
| 8 |
|
| 9 |
|
| 10 | |
| 11 | *
|
| 12 | * timeout_begin(TIMEOUT);
|
| 13 | * do {
|
| 14 | * ret = accept(...);
|
| 15 | * timeout_check("accept");
|
| 16 | * } while (ret < 0 && ret == EINTR);
|
| 17 | * timeout_end();
|
| 18 |
|
| 19 |
|
| 20 | #include <stdlib.h>
|
| 21 | #include <stdbool.h>
|
| 22 | #include <unistd.h>
|
| 23 | #include <stdio.h>
|
| 24 | #include <time.h>
|
| 25 | #include "timeout.h"
|
| 26 |
|
| 27 | static volatile bool timeout;
|
| 28 |
|
| 29 | |
| 30 | * setitimer(2) while using this API - they may interfere with each
|
| 31 | * other.
|
| 32 | *
|
| 33 | * If you need to sleep, please use timeout_sleep() provided by this API.
|
| 34 |
|
| 35 | void sigalrm(int signo)
|
| 36 | {
|
| 37 | timeout = true;
|
| 38 | }
|
| 39 |
|
| 40 | |
| 41 | * expired. timeout_end() must be called to stop the timeout. Timeouts cannot
|
| 42 | * be nested.
|
| 43 |
|
| 44 | void timeout_begin(unsigned int seconds)
|
| 45 | {
|
| 46 | alarm(seconds);
|
| 47 | }
|
| 48 |
|
| 49 |
|
| 50 | void timeout_check(const char *operation)
|
| 51 | {
|
| 52 | if (timeout) {
|
| 53 | fprintf(stderr, "%s timed out\n", operation);
|
| 54 | exit(EXIT_FAILURE);
|
| 55 | }
|
| 56 | }
|
| 57 |
|
| 58 |
|
| 59 | void timeout_end(void)
|
| 60 | {
|
| 61 | alarm(0);
|
| 62 | timeout = false;
|
| 63 | }
|
| 64 |
|
| 65 | |
| 66 | *
|
| 67 | * nanosleep(2) can be used with this API since POSIX.1 explicitly
|
| 68 | * specifies that it does not interact with signals.
|
| 69 |
|
| 70 | int timeout_usleep(useconds_t usec)
|
| 71 | {
|
| 72 | struct timespec ts = {
|
| 73 | .tv_sec = usec / 1000000,
|
| 74 | .tv_nsec = (usec % 1000000) * 1000,
|
| 75 | };
|
| 76 |
|
| 77 | return nanosleep(&ts, NULL);
|
| 78 | }
|