Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / 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/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   assert(func_scope_val == 0);
64   func_scope();
65   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   assert(shared_val != MAP_FAILED);
71
72   // test normal exit returning from main
73   *shared_val = 0;
74   int pid = fork();
75   assert(pid >= 0);
76   if (pid) {
77     int status;
78     int ret = waitpid(pid, &status, 0);
79     assert(ret == pid); // should be our child
80     assert(status == 0);
81     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     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   assert(pid >= 0);
97   if (pid) {
98     int status;
99     int ret = waitpid(pid, &status, 0);
100     assert(ret == pid); // should be our child
101     assert(WEXITSTATUS(status) == 3);
102     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     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 }