]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | #include <sys/mman.h> |
2 | #include <sys/types.h> | |
3 | #include <sys/wait.h> | |
4 | #include <stdlib.h> | |
5 | #include <unistd.h> | |
6 | #include "include/on_exit.h" | |
11fdf7f2 | 7 | #include "include/ceph_assert.h" |
7c673cae FG |
8 | |
9 | #ifndef MAP_ANONYMOUS | |
10 | # ifdef MAP_ANON | |
11 | # define MAP_ANONYMOUS MAP_ANON | |
12 | # else | |
13 | // cppcheck-suppress preprocessorErrorDirective | |
14 | # error "Don't know how to create anonymous mmap" | |
15 | # endif | |
16 | #endif | |
17 | ||
18 | static int func_scope_val; | |
19 | ||
20 | static void add(void *incp) | |
21 | { | |
22 | func_scope_val += *((int*)incp); | |
23 | } | |
24 | ||
25 | static void func_scope(void) | |
26 | { | |
27 | OnExitManager mgr; | |
28 | ||
29 | int *inc_1 = (int*)malloc(sizeof(*inc_1)); | |
30 | *inc_1 = 5; | |
31 | mgr.add_callback(add, inc_1); | |
32 | ||
33 | int *inc_2 = (int*)malloc(sizeof(*inc_2)); | |
34 | *inc_2 = 3; | |
35 | mgr.add_callback(add, inc_2); | |
36 | } | |
37 | ||
38 | // shared between processes | |
39 | static int *shared_val; | |
40 | ||
41 | #define MAIN_SCOPE_VAL 0x1111111 | |
42 | static OnExitManager main_scope_mgr; | |
43 | static void main_scope_cb(void *val) | |
44 | { | |
45 | *shared_val = *((int*)val); | |
46 | } | |
47 | ||
48 | #define EXIT_FUNC_VAL 0x22222222 | |
49 | static OnExitManager exit_func_mgr; | |
50 | static void exit_func_cb(void *val) | |
51 | { | |
52 | *shared_val = *((int*)val); | |
53 | } | |
54 | ||
55 | static void call_exit() | |
56 | { | |
57 | exit(3); | |
58 | } | |
59 | ||
60 | int main(int argc, char **argv) | |
61 | { | |
62 | // test basic function scope behavior | |
11fdf7f2 | 63 | ceph_assert(func_scope_val == 0); |
7c673cae | 64 | func_scope(); |
11fdf7f2 | 65 | ceph_assert(func_scope_val == 8); |
7c673cae FG |
66 | |
67 | // shared mem for exit tests | |
68 | shared_val = (int*)mmap(NULL, sizeof(int), | |
69 | PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0); | |
11fdf7f2 | 70 | ceph_assert(shared_val != MAP_FAILED); |
7c673cae FG |
71 | |
72 | // test normal exit returning from main | |
73 | *shared_val = 0; | |
74 | int pid = fork(); | |
11fdf7f2 | 75 | ceph_assert(pid >= 0); |
7c673cae FG |
76 | if (pid) { |
77 | int status; | |
78 | int ret = waitpid(pid, &status, 0); | |
11fdf7f2 TL |
79 | ceph_assert(ret == pid); // should be our child |
80 | ceph_assert(status == 0); | |
81 | ceph_assert(*shared_val == MAIN_SCOPE_VAL); | |
7c673cae FG |
82 | } else { |
83 | // child adds a callback to the static scope callback manager and then | |
84 | // exits by returning from main. The parent checks the value after the | |
85 | // child exits via the memory map. | |
11fdf7f2 | 86 | ceph_assert(*shared_val == 0); |
7c673cae FG |
87 | int *new_val = (int*)malloc(sizeof(*new_val)); |
88 | *new_val = MAIN_SCOPE_VAL; | |
89 | main_scope_mgr.add_callback(main_scope_cb, new_val); | |
90 | return 0; | |
91 | } | |
92 | ||
93 | // test exit via exit() | |
94 | *shared_val = 0; | |
95 | pid = fork(); | |
11fdf7f2 | 96 | ceph_assert(pid >= 0); |
7c673cae FG |
97 | if (pid) { |
98 | int status; | |
99 | int ret = waitpid(pid, &status, 0); | |
11fdf7f2 TL |
100 | ceph_assert(ret == pid); // should be our child |
101 | ceph_assert(WEXITSTATUS(status) == 3); | |
102 | ceph_assert(*shared_val == EXIT_FUNC_VAL); | |
7c673cae FG |
103 | } else { |
104 | // child adds a callback to the static scope callback manager and then | |
105 | // exits via exit(). | |
11fdf7f2 | 106 | ceph_assert(*shared_val == 0); |
7c673cae FG |
107 | int *new_val = (int*)malloc(sizeof(*new_val)); |
108 | *new_val = EXIT_FUNC_VAL; | |
109 | exit_func_mgr.add_callback(exit_func_cb, new_val); | |
110 | call_exit(); | |
111 | ceph_abort(); | |
112 | } | |
113 | ||
114 | return 0; | |
115 | } |