]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/on_exit.cc
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / test / on_exit.cc
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"
7 #include "include/ceph_assert.h"
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
63 ceph_assert(func_scope_val == 0);
64 func_scope();
65 ceph_assert(func_scope_val == 8);
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);
70 ceph_assert(shared_val != MAP_FAILED);
71
72 // test normal exit returning from main
73 *shared_val = 0;
74 int pid = fork();
75 ceph_assert(pid >= 0);
76 if (pid) {
77 int status;
78 int ret = waitpid(pid, &status, 0);
79 ceph_assert(ret == pid); // should be our child
80 ceph_assert(status == 0);
81 ceph_assert(*shared_val == MAIN_SCOPE_VAL);
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.
86 ceph_assert(*shared_val == 0);
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();
96 ceph_assert(pid >= 0);
97 if (pid) {
98 int status;
99 int ret = waitpid(pid, &status, 0);
100 ceph_assert(ret == pid); // should be our child
101 ceph_assert(WEXITSTATUS(status) == 3);
102 ceph_assert(*shared_val == EXIT_FUNC_VAL);
103 } else {
104 // child adds a callback to the static scope callback manager and then
105 // exits via exit().
106 ceph_assert(*shared_val == 0);
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 }