Bump version to 19.1.0 (final)
[llvm-project.git] / lldb / test / Shell / Subprocess / Inputs / fork.cpp
blob81b1d116c9436eb40f8cddca5f45946d957983e7
1 #include <sys/types.h>
2 #include <sys/wait.h>
3 #include <assert.h>
4 #if defined(TEST_CLONE)
5 #include <sched.h>
6 #endif
7 #include <stdint.h>
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include <unistd.h>
12 int g_val = 0;
14 void parent_func() {
15 g_val = 1;
16 printf("function run in parent\n");
19 int parent_done[2];
20 char parent_done_str[16];
22 void wait_for_parent() {
23 char buf[2];
24 // wait for the parent to finish its part
25 int ret = read(parent_done[0], buf, sizeof(buf));
26 assert(ret == 2);
27 ret = close(parent_done[0]);
28 assert(ret == 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
36 g_val = 2;
37 g_val = 0;
38 execl(argv0, argv0, parent_done_str, NULL);
39 assert(0 && "this should not be reached");
40 return 1;
43 int child_top_func(void *argv0_ptr) {
44 const char *argv0 = static_cast<char*>(argv0_ptr);
46 int ret = close(parent_done[1]);
47 assert(ret == 0);
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)
53 #endif
54 wait_for_parent();
56 return child_func(argv0);
59 int main(int argc, char* argv[]) {
60 alignas(uintmax_t) char stack[4096];
61 int ret;
63 if (argv[1]) {
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)
70 wait_for_parent();
71 #endif
73 fprintf(stderr, "function run in exec'd child\n");
74 return 0;
77 ret = pipe(parent_done);
78 assert(ret == 0);
80 ret = snprintf(parent_done_str, sizeof(parent_done_str),
81 "%d", parent_done[0]);
82 assert(ret != -1);
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
89 if (pid == 0)
90 _exit(child_top_func(argv[0]));
91 #endif
92 assert(pid != -1);
94 ret = close(parent_done[0]);
95 assert(ret == 0);
97 parent_func();
99 // resume the child
100 ret = write(parent_done[1], "go", 2);
101 assert(ret == 2);
102 ret = close(parent_done[1]);
103 assert(ret == 0);
105 int status, wait_flags = 0;
106 #if defined(TEST_CLONE)
107 wait_flags = __WALL;
108 #endif
109 pid_t waited = waitpid(pid, &status, wait_flags);
110 assert(waited == pid);
111 assert(WIFEXITED(status));
112 assert(WEXITSTATUS(status) == 0);
114 return 0;