harness.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  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 <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 TIMEOUT 120
  20. #define KILL_TIMEOUT 5
  21. int run_test(int (test_function)(void), char *name)
  22. {
  23. bool terminated;
  24. int rc, status;
  25. pid_t pid;
  26. /* Make sure output is flushed before forking */
  27. fflush(stdout);
  28. pid = fork();
  29. if (pid == 0) {
  30. setpgid(0, 0);
  31. exit(test_function());
  32. } else if (pid == -1) {
  33. perror("fork");
  34. return 1;
  35. }
  36. setpgid(pid, pid);
  37. /* Wake us up in timeout seconds */
  38. alarm(TIMEOUT);
  39. terminated = false;
  40. wait:
  41. rc = waitpid(pid, &status, 0);
  42. if (rc == -1) {
  43. if (errno != EINTR) {
  44. printf("unknown error from waitpid\n");
  45. return 1;
  46. }
  47. if (terminated) {
  48. printf("!! force killing %s\n", name);
  49. kill(-pid, SIGKILL);
  50. return 1;
  51. } else {
  52. printf("!! killing %s\n", name);
  53. kill(-pid, SIGTERM);
  54. terminated = true;
  55. alarm(KILL_TIMEOUT);
  56. goto wait;
  57. }
  58. }
  59. /* Kill anything else in the process group that is still running */
  60. kill(-pid, SIGTERM);
  61. if (WIFEXITED(status))
  62. status = WEXITSTATUS(status);
  63. else {
  64. if (WIFSIGNALED(status))
  65. printf("!! child died by signal %d\n", WTERMSIG(status));
  66. else
  67. printf("!! child died by unknown cause\n");
  68. status = 1; /* Signal or other */
  69. }
  70. return status;
  71. }
  72. static void alarm_handler(int signum)
  73. {
  74. /* Jut wake us up from waitpid */
  75. }
  76. static struct sigaction alarm_action = {
  77. .sa_handler = alarm_handler,
  78. };
  79. int test_harness(int (test_function)(void), char *name)
  80. {
  81. int rc;
  82. test_start(name);
  83. test_set_git_version(GIT_VERSION);
  84. if (sigaction(SIGALRM, &alarm_action, NULL)) {
  85. perror("sigaction");
  86. test_error(name);
  87. return 1;
  88. }
  89. rc = run_test(test_function, name);
  90. if (rc == MAGIC_SKIP_RETURN_VALUE)
  91. test_skip(name);
  92. else
  93. test_finish(name, rc);
  94. return rc;
  95. }
  96. static char auxv[4096];
  97. void *get_auxv_entry(int type)
  98. {
  99. ElfW(auxv_t) *p;
  100. void *result;
  101. ssize_t num;
  102. int fd;
  103. fd = open("/proc/self/auxv", O_RDONLY);
  104. if (fd == -1) {
  105. perror("open");
  106. return NULL;
  107. }
  108. result = NULL;
  109. num = read(fd, auxv, sizeof(auxv));
  110. if (num < 0) {
  111. perror("read");
  112. goto out;
  113. }
  114. if (num > sizeof(auxv)) {
  115. printf("Overflowed auxv buffer\n");
  116. goto out;
  117. }
  118. p = (ElfW(auxv_t) *)auxv;
  119. while (p->a_type != AT_NULL) {
  120. if (p->a_type == type) {
  121. result = (void *)p->a_un.a_val;
  122. break;
  123. }
  124. p++;
  125. }
  126. out:
  127. close(fd);
  128. return result;
  129. }