harness.c 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. /*
  2. * Copyright 2013, Michael Ellerman, IBM Corp.
  3. * Licensed under GPLv2.
  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 "subunit.h"
  14. #include "utils.h"
  15. #define TIMEOUT 120
  16. #define KILL_TIMEOUT 5
  17. int run_test(int (test_function)(void), char *name)
  18. {
  19. bool terminated;
  20. int rc, status;
  21. pid_t pid;
  22. /* Make sure output is flushed before forking */
  23. fflush(stdout);
  24. pid = fork();
  25. if (pid == 0) {
  26. setpgid(0, 0);
  27. exit(test_function());
  28. } else if (pid == -1) {
  29. perror("fork");
  30. return 1;
  31. }
  32. setpgid(pid, pid);
  33. /* Wake us up in timeout seconds */
  34. alarm(TIMEOUT);
  35. terminated = false;
  36. wait:
  37. rc = waitpid(pid, &status, 0);
  38. if (rc == -1) {
  39. if (errno != EINTR) {
  40. printf("unknown error from waitpid\n");
  41. return 1;
  42. }
  43. if (terminated) {
  44. printf("!! force killing %s\n", name);
  45. kill(-pid, SIGKILL);
  46. return 1;
  47. } else {
  48. printf("!! killing %s\n", name);
  49. kill(-pid, SIGTERM);
  50. terminated = true;
  51. alarm(KILL_TIMEOUT);
  52. goto wait;
  53. }
  54. }
  55. /* Kill anything else in the process group that is still running */
  56. kill(-pid, SIGTERM);
  57. if (WIFEXITED(status))
  58. status = WEXITSTATUS(status);
  59. else {
  60. if (WIFSIGNALED(status))
  61. printf("!! child died by signal %d\n", WTERMSIG(status));
  62. else
  63. printf("!! child died by unknown cause\n");
  64. status = 1; /* Signal or other */
  65. }
  66. return status;
  67. }
  68. static void alarm_handler(int signum)
  69. {
  70. /* Jut wake us up from waitpid */
  71. }
  72. static struct sigaction alarm_action = {
  73. .sa_handler = alarm_handler,
  74. };
  75. int test_harness(int (test_function)(void), char *name)
  76. {
  77. int rc;
  78. test_start(name);
  79. test_set_git_version(GIT_VERSION);
  80. if (sigaction(SIGALRM, &alarm_action, NULL)) {
  81. perror("sigaction");
  82. test_error(name);
  83. return 1;
  84. }
  85. rc = run_test(test_function, name);
  86. if (rc == MAGIC_SKIP_RETURN_VALUE)
  87. test_skip(name);
  88. else
  89. test_finish(name, rc);
  90. return rc;
  91. }