10 #include <darwintest.h>
13 // Exercise races of signal delivery vs exec in multi-threaded processes
15 T_GLOBAL_META(T_META_NAMESPACE("xnu.exec"),
16 T_META_CHECK_LEAKS(false),
17 T_META_ALL_VALID_ARCHS(true));
19 enum { KILL_ONCE
, KILL_MANY
, KILL_LAST
} kill_mode
;
20 enum { EXEC_FIRST
, EXEC_SECOND
, EXEC_LAST
} exec_mode
;
27 char echo_arg
[50] = "";
29 snprintf(echo_arg
, sizeof(echo_arg
), " Child[%d] says hello after exec", getpid());
37 int ret
= execv(new_argv
[0], new_argv
);
38 T_QUIET
; T_ASSERT_POSIX_SUCCESS(ret
, "execv()");
42 thread_main(void* arg
)
44 T_LOG("mode: %d, %d: Child[%d] created second thread\n",
45 kill_mode
, exec_mode
, getpid());
47 if (exec_mode
== EXEC_SECOND
) {
48 int ret
= dprintf(fd
[1], "Hi!");
49 T_QUIET
; T_ASSERT_POSIX_SUCCESS(ret
, "dprintf()");
61 T_LOG("mode: %d, %d: Parent[%d]: forking\n",
62 kill_mode
, exec_mode
, getpid());
64 pid_t child_pid
= fork();
66 T_QUIET
; T_ASSERT_POSIX_SUCCESS(child_pid
, "fork()");
72 ret
= pthread_create(&thread
, NULL
, thread_main
, NULL
);
73 T_QUIET
; T_ASSERT_POSIX_SUCCESS(ret
, "pthread_create()");
75 if (exec_mode
== EXEC_FIRST
) {
76 ret
= dprintf(fd
[1], "Hi!");
77 T_QUIET
; T_ASSERT_POSIX_SUCCESS(ret
, "dprintf()");
86 ret
= read(fd
[0], buffer
, sizeof(buffer
));
87 T_QUIET
; T_ASSERT_POSIX_SUCCESS(ret
, "read()");
89 T_LOG("mode: %d, %d: Parent[%d]: got: '%s' from execing child, trying to kill and wait\n",
90 kill_mode
, exec_mode
, getpid(), buffer
);
92 int killcount
= 0, status
= 0, waitedpid
= 0;
96 ret
= kill(child_pid
, SIGKILL
);
97 T_QUIET
; T_ASSERT_POSIX_SUCCESS(ret
, "kill()");
99 waitedpid
= waitpid(child_pid
, &status
, 0);
101 T_QUIET
; T_ASSERT_POSIX_SUCCESS(waitedpid
, "waitpid()");
106 while (waitedpid
== 0) {
107 ret
= kill(child_pid
, SIGKILL
);
108 T_QUIET
; T_ASSERT_POSIX_SUCCESS(ret
, "kill()");
110 waitedpid
= waitpid(child_pid
, &status
, WNOHANG
);
111 T_QUIET
; T_ASSERT_POSIX_SUCCESS(waitedpid
, "waitpid()");
120 T_LOG("mode: %d, %d: Parent[%d]: waitpid returned: %d, errno %d (%s), exit signal %d, after %d loops\n",
121 kill_mode
, exec_mode
, getpid(), waitedpid
, errno
, strerror(errno
), WTERMSIG(status
), killcount
);
125 T_DECL(exec_exit_race_once_first
, "Exec-exit race, one kill, exec on first thread") {
127 T_QUIET
; T_ASSERT_POSIX_SUCCESS(rv
, "pipe()");
129 kill_mode
= KILL_ONCE
;
130 exec_mode
= EXEC_FIRST
;
132 for (int i
= 0; i
< 1000; i
++) {
137 T_DECL(exec_exit_race_many_first
, "Exec-exit race, many kill, exec on first thread") {
139 T_QUIET
; T_ASSERT_POSIX_SUCCESS(rv
, "pipe()");
141 kill_mode
= KILL_MANY
;
142 exec_mode
= EXEC_FIRST
;
144 for (int i
= 0; i
< 1000; i
++) {
149 T_DECL(exec_exit_race_once_second
, "Exec-exit race, one kill, exec on second thread") {
151 T_QUIET
; T_ASSERT_POSIX_SUCCESS(rv
, "pipe()");
153 kill_mode
= KILL_ONCE
;
154 exec_mode
= EXEC_SECOND
;
156 for (int i
= 0; i
< 1000; i
++) {
161 T_DECL(exec_exit_race_many_second
, "Exec-exit race, many kill, exec on second thread") {
163 T_QUIET
; T_ASSERT_POSIX_SUCCESS(rv
, "pipe()");
165 kill_mode
= KILL_MANY
;
166 exec_mode
= EXEC_SECOND
;
168 for (int i
= 0; i
< 1000; i
++) {