1 #include <darwintest.h>
4 #include <mach/mach_types.h>
7 #include <dispatch/dispatch.h>
12 T_LOG("Helper thread running: %d", (bool)corrupt
);
14 // The pthread_t is stored at the top of the stack and could be
15 // corrupted because of a stack overflow. To make the test more
16 // reliable, we will manually smash the pthread struct directly.
17 pthread_t self
= pthread_self();
18 memset(self
, 0x41, 4096);
20 // Expected behavior is that if a thread calls abort, the process should
23 T_FAIL("Abort didn't?");
26 typedef enum { PTHREAD
, WORKQUEUE
} thread_type_t
;
29 abort_test(thread_type_t type
, int expected_signal
)
32 bool corrupt
= expected_signal
== SIGSEGV
;
35 T_LOG("Child running");
41 pthread_create(&tid
, NULL
, body
, (void *)corrupt
), NULL
);
45 dispatch_async_f(dispatch_get_global_queue(
46 DISPATCH_QUEUE_PRIORITY_DEFAULT
, 0),
47 (void *)corrupt
, &body
);
52 T_FAIL("Child didn't abort");
55 // Wait and check the exit status of the child
57 pid_t pid
= wait(&status
);
59 T_ASSERT_EQ(pid
, child
, NULL
);
61 T_EXPECT_FALSE(WIFEXITED(status
), "WIFEXITED Status: %x", status
);
63 T_EXPECT_TRUE(WIFSIGNALED(status
), "WIFSIGNALED Status: %x", status
);
65 T_EXPECT_FALSE(WIFSTOPPED(status
), "WIFSTOPPED Status: %x", status
);
66 // This test is successful if we trigger a SIGSEGV|SIGBUS or SIGABRT
67 // since both will promptly terminate the program
68 int signal
= WTERMSIG(status
);
69 if (signal
== SIGBUS
) {
71 T_LOG("Converting %d to SIGSEGV", signal
);
74 T_EXPECT_EQ(signal
, expected_signal
, NULL
);
79 signal_handler(int signo
)
81 // The user's signal handler should not be called during abort
82 T_FAIL("Unexpected signal: %d\n", signo
);
85 T_DECL(abort_pthread_corrupt_test
, "Tests abort")
87 abort_test(PTHREAD
, SIGSEGV
);
90 T_DECL(abort_workqueue_corrupt_test
, "Tests abort")
92 abort_test(WORKQUEUE
, SIGSEGV
);
95 T_DECL(abort_pthread_handler_test
, "Tests abort")
98 T_SKIP("Abort hangs if the user registers their own SIGSEGV handler");
99 signal(SIGSEGV
, signal_handler
);
100 abort_test(PTHREAD
, SIGSEGV
);
103 T_DECL(abort_workqueue_handler_test
, "Tests abort")
106 T_SKIP("Abort hangs if the user registers their own SIGSEGV handler");
107 signal(SIGSEGV
, signal_handler
);
108 abort_test(WORKQUEUE
, SIGSEGV
);
111 T_DECL(abort_pthread_test
, "Tests abort")
113 abort_test(PTHREAD
, SIGABRT
);
116 T_DECL(abort_workqueue_test
, "Tests abort")
118 abort_test(WORKQUEUE
, SIGABRT
);