2
0

fork.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. #include "test/jemalloc_test.h"
  2. #ifndef _WIN32
  3. #include <sys/wait.h>
  4. #endif
  5. #ifndef _WIN32
  6. static void
  7. wait_for_child_exit(int pid) {
  8. int status;
  9. while (true) {
  10. if (waitpid(pid, &status, 0) == -1) {
  11. test_fail("Unexpected waitpid() failure.");
  12. }
  13. if (WIFSIGNALED(status)) {
  14. test_fail("Unexpected child termination due to "
  15. "signal %d", WTERMSIG(status));
  16. break;
  17. }
  18. if (WIFEXITED(status)) {
  19. if (WEXITSTATUS(status) != 0) {
  20. test_fail("Unexpected child exit value %d",
  21. WEXITSTATUS(status));
  22. }
  23. break;
  24. }
  25. }
  26. }
  27. #endif
  28. TEST_BEGIN(test_fork) {
  29. #ifndef _WIN32
  30. void *p;
  31. pid_t pid;
  32. /* Set up a manually managed arena for test. */
  33. unsigned arena_ind;
  34. size_t sz = sizeof(unsigned);
  35. assert_d_eq(mallctl("arenas.create", (void *)&arena_ind, &sz, NULL, 0),
  36. 0, "Unexpected mallctl() failure");
  37. /* Migrate to the new arena. */
  38. unsigned old_arena_ind;
  39. sz = sizeof(old_arena_ind);
  40. assert_d_eq(mallctl("thread.arena", (void *)&old_arena_ind, &sz,
  41. (void *)&arena_ind, sizeof(arena_ind)), 0,
  42. "Unexpected mallctl() failure");
  43. p = malloc(1);
  44. assert_ptr_not_null(p, "Unexpected malloc() failure");
  45. pid = fork();
  46. free(p);
  47. p = malloc(64);
  48. assert_ptr_not_null(p, "Unexpected malloc() failure");
  49. free(p);
  50. if (pid == -1) {
  51. /* Error. */
  52. test_fail("Unexpected fork() failure");
  53. } else if (pid == 0) {
  54. /* Child. */
  55. _exit(0);
  56. } else {
  57. wait_for_child_exit(pid);
  58. }
  59. #else
  60. test_skip("fork(2) is irrelevant to Windows");
  61. #endif
  62. }
  63. TEST_END
  64. #ifndef _WIN32
  65. static void *
  66. do_fork_thd(void *arg) {
  67. malloc(1);
  68. int pid = fork();
  69. if (pid == -1) {
  70. /* Error. */
  71. test_fail("Unexpected fork() failure");
  72. } else if (pid == 0) {
  73. /* Child. */
  74. char *args[] = {"true", NULL};
  75. execvp(args[0], args);
  76. test_fail("Exec failed");
  77. } else {
  78. /* Parent */
  79. wait_for_child_exit(pid);
  80. }
  81. return NULL;
  82. }
  83. #endif
  84. #ifndef _WIN32
  85. static void
  86. do_test_fork_multithreaded() {
  87. thd_t child;
  88. thd_create(&child, do_fork_thd, NULL);
  89. do_fork_thd(NULL);
  90. thd_join(child, NULL);
  91. }
  92. #endif
  93. TEST_BEGIN(test_fork_multithreaded) {
  94. #ifndef _WIN32
  95. /*
  96. * We've seen bugs involving hanging on arenas_lock (though the same
  97. * class of bugs can happen on any mutex). The bugs are intermittent
  98. * though, so we want to run the test multiple times. Since we hold the
  99. * arenas lock only early in the process lifetime, we can't just run
  100. * this test in a loop (since, after all the arenas are initialized, we
  101. * won't acquire arenas_lock any further). We therefore repeat the test
  102. * with multiple processes.
  103. */
  104. for (int i = 0; i < 100; i++) {
  105. int pid = fork();
  106. if (pid == -1) {
  107. /* Error. */
  108. test_fail("Unexpected fork() failure,");
  109. } else if (pid == 0) {
  110. /* Child. */
  111. do_test_fork_multithreaded();
  112. _exit(0);
  113. } else {
  114. wait_for_child_exit(pid);
  115. }
  116. }
  117. #else
  118. test_skip("fork(2) is irrelevant to Windows");
  119. #endif
  120. }
  121. TEST_END
  122. int
  123. main(void) {
  124. return test_no_reentrancy(
  125. test_fork,
  126. test_fork_multithreaded);
  127. }