timeout.c 1.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /* Timeout API for single-threaded programs that use blocking
  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. /* Use the following pattern:
  10. *
  11. * timeout_begin(TIMEOUT);
  12. * do {
  13. * ret = accept(...);
  14. * timeout_check("accept");
  15. * } while (ret < 0 && ret == EINTR);
  16. * timeout_end();
  17. */
  18. #include <stdlib.h>
  19. #include <stdbool.h>
  20. #include <unistd.h>
  21. #include <stdio.h>
  22. #include "timeout.h"
  23. static volatile bool timeout;
  24. /* SIGALRM handler function. Do not use sleep(2), alarm(2), or
  25. * setitimer(2) while using this API - they may interfere with each
  26. * other.
  27. */
  28. void sigalrm(int signo)
  29. {
  30. timeout = true;
  31. }
  32. /* Start a timeout. Call timeout_check() to verify that the timeout hasn't
  33. * expired. timeout_end() must be called to stop the timeout. Timeouts cannot
  34. * be nested.
  35. */
  36. void timeout_begin(unsigned int seconds)
  37. {
  38. alarm(seconds);
  39. }
  40. /* Exit with an error message if the timeout has expired */
  41. void timeout_check(const char *operation)
  42. {
  43. if (timeout) {
  44. fprintf(stderr, "%s timed out\n", operation);
  45. exit(EXIT_FAILURE);
  46. }
  47. }
  48. /* Stop a timeout */
  49. void timeout_end(void)
  50. {
  51. alarm(0);
  52. timeout = false;
  53. }