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