]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/on_exit.cc
buildsys: switch source download to quincy
[ceph.git] / ceph / src / test / on_exit.cc
CommitLineData
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
18static int func_scope_val;
19
20static void add(void *incp)
21{
22 func_scope_val += *((int*)incp);
23}
24
25static 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
39static int *shared_val;
40
41#define MAIN_SCOPE_VAL 0x1111111
42static OnExitManager main_scope_mgr;
43static void main_scope_cb(void *val)
44{
45 *shared_val = *((int*)val);
46}
47
48#define EXIT_FUNC_VAL 0x22222222
49static OnExitManager exit_func_mgr;
50static void exit_func_cb(void *val)
51{
52 *shared_val = *((int*)val);
53}
54
55static void call_exit()
56{
57 exit(3);
58}
59
60int 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}