4 #if defined(TEST_CLONE)
16 printf("function run in parent\n");
20 char parent_done_str
[16];
22 void wait_for_parent() {
24 // wait for the parent to finish its part
25 int ret
= read(parent_done
[0], buf
, sizeof(buf
));
27 ret
= close(parent_done
[0]);
31 // This is the function we set breakpoint on.
32 int child_func(const char *argv0
) {
33 // we need to avoid memory modifications for vfork(), yet we want
34 // to be able to test watchpoints, so do the next best thing
35 // and restore the original value
38 execl(argv0
, argv0
, parent_done_str
, NULL
);
39 assert(0 && "this should not be reached");
43 int child_top_func(void *argv0_ptr
) {
44 const char *argv0
= static_cast<char*>(argv0_ptr
);
46 int ret
= close(parent_done
[1]);
49 // NB: when using vfork(), the parent may be suspended while running
50 // this function, so do not rely on any synchronization until we exec
51 #if defined(TEST_FORK)
52 if (TEST_FORK
!= vfork
)
56 return child_func(argv0
);
59 int main(int argc
, char* argv
[]) {
60 alignas(uintmax_t) char stack
[4096];
64 parent_done
[0] = atoi(argv
[1]);
65 assert(parent_done
[0] != 0);
67 #if defined(TEST_FORK)
68 // for vfork(), we need to synchronize after exec
69 if (TEST_FORK
== vfork
)
73 fprintf(stderr
, "function run in exec'd child\n");
77 ret
= pipe(parent_done
);
80 ret
= snprintf(parent_done_str
, sizeof(parent_done_str
),
81 "%d", parent_done
[0]);
84 #if defined(TEST_CLONE)
85 pid_t pid
= clone(child_top_func
, &stack
[sizeof(stack
)], 0, argv
[0]);
86 #elif defined(TEST_FORK)
87 pid_t pid
= TEST_FORK();
88 // NB: this must be equivalent to the clone() call above
90 _exit(child_top_func(argv
[0]));
94 ret
= close(parent_done
[0]);
100 ret
= write(parent_done
[1], "go", 2);
102 ret
= close(parent_done
[1]);
105 int status
, wait_flags
= 0;
106 #if defined(TEST_CLONE)
109 pid_t waited
= waitpid(pid
, &status
, wait_flags
);
110 assert(waited
== pid
);
111 assert(WIFEXITED(status
));
112 assert(WEXITSTATUS(status
) == 0);