harness.c 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  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. exit(test_function());
  27. } else if (pid == -1) {
  28. perror("fork");
  29. return 1;
  30. }
  31. /* Wake us up in timeout seconds */
  32. alarm(TIMEOUT);
  33. terminated = false;
  34. wait:
  35. rc = waitpid(pid, &status, 0);
  36. if (rc == -1) {
  37. if (errno != EINTR) {
  38. printf("unknown error from waitpid\n");
  39. return 1;
  40. }
  41. if (terminated) {
  42. printf("!! force killing %s\n", name);
  43. kill(pid, SIGKILL);
  44. return 1;
  45. } else {
  46. printf("!! killing %s\n", name);
  47. kill(pid, SIGTERM);
  48. terminated = true;
  49. alarm(KILL_TIMEOUT);
  50. goto wait;
  51. }
  52. }
  53. if (WIFEXITED(status))
  54. status = WEXITSTATUS(status);
  55. else {
  56. if (WIFSIGNALED(status))
  57. printf("!! child died by signal %d\n", WTERMSIG(status));
  58. else
  59. printf("!! child died by unknown cause\n");
  60. status = 1; /* Signal or other */
  61. }
  62. return status;
  63. }
  64. static void alarm_handler(int signum)
  65. {
  66. /* Jut wake us up from waitpid */
  67. }
  68. static struct sigaction alarm_action = {
  69. .sa_handler = alarm_handler,
  70. };
  71. int test_harness(int (test_function)(void), char *name)
  72. {
  73. int rc;
  74. test_start(name);
  75. test_set_git_version(GIT_VERSION);
  76. if (sigaction(SIGALRM, &alarm_action, NULL)) {
  77. perror("sigaction");
  78. test_error(name);
  79. return 1;
  80. }
  81. rc = run_test(test_function, name);
  82. test_finish(name, rc);
  83. return rc;
  84. }