harness.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright 2013, Michael Ellerman, IBM Corp.
  4. */
  5. #include <errno.h>
  6. #include <signal.h>
  7. #include <stdbool.h>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <sys/types.h>
  11. #include <sys/wait.h>
  12. #include <unistd.h>
  13. #include <elf.h>
  14. #include <fcntl.h>
  15. #include <link.h>
  16. #include <sys/stat.h>
  17. #include "subunit.h"
  18. #include "utils.h"
  19. #define KILL_TIMEOUT 5
  20. /* Setting timeout to -1 disables the alarm */
  21. static uint64_t timeout = 120;
  22. int run_test(int (test_function)(void), char *name)
  23. {
  24. bool terminated;
  25. int rc, status;
  26. pid_t pid;
  27. /* Make sure output is flushed before forking */
  28. fflush(stdout);
  29. pid = fork();
  30. if (pid == 0) {
  31. setpgid(0, 0);
  32. exit(test_function());
  33. } else if (pid == -1) {
  34. perror("fork");
  35. return 1;
  36. }
  37. setpgid(pid, pid);
  38. if (timeout != -1)
  39. /* Wake us up in timeout seconds */
  40. alarm(timeout);
  41. terminated = false;
  42. wait:
  43. rc = waitpid(pid, &status, 0);
  44. if (rc == -1) {
  45. if (errno != EINTR) {
  46. printf("unknown error from waitpid\n");
  47. return 1;
  48. }
  49. if (terminated) {
  50. printf("!! force killing %s\n", name);
  51. kill(-pid, SIGKILL);
  52. return 1;
  53. } else {
  54. printf("!! killing %s\n", name);
  55. kill(-pid, SIGTERM);
  56. terminated = true;
  57. alarm(KILL_TIMEOUT);
  58. goto wait;
  59. }
  60. }
  61. /* Kill anything else in the process group that is still running */
  62. kill(-pid, SIGTERM);
  63. if (WIFEXITED(status))
  64. status = WEXITSTATUS(status);
  65. else {
  66. if (WIFSIGNALED(status))
  67. printf("!! child died by signal %d\n", WTERMSIG(status));
  68. else
  69. printf("!! child died by unknown cause\n");
  70. status = 1; /* Signal or other */
  71. }
  72. return status;
  73. }
  74. static void sig_handler(int signum)
  75. {
  76. /* Just wake us up from waitpid */
  77. }
  78. static struct sigaction sig_action = {
  79. .sa_handler = sig_handler,
  80. };
  81. void test_harness_set_timeout(uint64_t time)
  82. {
  83. timeout = time;
  84. }
  85. int test_harness(int (test_function)(void), char *name)
  86. {
  87. int rc;
  88. test_start(name);
  89. test_set_git_version(GIT_VERSION);
  90. if (sigaction(SIGINT, &sig_action, NULL)) {
  91. perror("sigaction (sigint)");
  92. test_error(name);
  93. return 1;
  94. }
  95. if (sigaction(SIGALRM, &sig_action, NULL)) {
  96. perror("sigaction (sigalrm)");
  97. test_error(name);
  98. return 1;
  99. }
  100. rc = run_test(test_function, name);
  101. if (rc == MAGIC_SKIP_RETURN_VALUE) {
  102. test_skip(name);
  103. /* so that skipped test is not marked as failed */
  104. rc = 0;
  105. } else
  106. test_finish(name, rc);
  107. return rc;
  108. }