X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fceph%2Fsrc%2Ftest%2Fon_exit.cc;fp=src%2Fceph%2Fsrc%2Ftest%2Fon_exit.cc;h=50721ac0da70a239c0f88441e65ad710a5915d01;hb=812ff6ca9fcd3e629e49d4328905f33eee8ca3f5;hp=0000000000000000000000000000000000000000;hpb=15280273faafb77777eab341909a3f495cf248d9;p=stor4nfv.git diff --git a/src/ceph/src/test/on_exit.cc b/src/ceph/src/test/on_exit.cc new file mode 100644 index 0000000..50721ac --- /dev/null +++ b/src/ceph/src/test/on_exit.cc @@ -0,0 +1,115 @@ +#include +#include +#include +#include +#include +#include "include/on_exit.h" +#include "include/assert.h" + +#ifndef MAP_ANONYMOUS +# ifdef MAP_ANON +# define MAP_ANONYMOUS MAP_ANON +# else +// cppcheck-suppress preprocessorErrorDirective +# error "Don't know how to create anonymous mmap" +# endif +#endif + +static int func_scope_val; + +static void add(void *incp) +{ + func_scope_val += *((int*)incp); +} + +static void func_scope(void) +{ + OnExitManager mgr; + + int *inc_1 = (int*)malloc(sizeof(*inc_1)); + *inc_1 = 5; + mgr.add_callback(add, inc_1); + + int *inc_2 = (int*)malloc(sizeof(*inc_2)); + *inc_2 = 3; + mgr.add_callback(add, inc_2); +} + +// shared between processes +static int *shared_val; + +#define MAIN_SCOPE_VAL 0x1111111 +static OnExitManager main_scope_mgr; +static void main_scope_cb(void *val) +{ + *shared_val = *((int*)val); +} + +#define EXIT_FUNC_VAL 0x22222222 +static OnExitManager exit_func_mgr; +static void exit_func_cb(void *val) +{ + *shared_val = *((int*)val); +} + +static void call_exit() +{ + exit(3); +} + +int main(int argc, char **argv) +{ + // test basic function scope behavior + assert(func_scope_val == 0); + func_scope(); + assert(func_scope_val == 8); + + // shared mem for exit tests + shared_val = (int*)mmap(NULL, sizeof(int), + PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0); + assert(shared_val != MAP_FAILED); + + // test normal exit returning from main + *shared_val = 0; + int pid = fork(); + assert(pid >= 0); + if (pid) { + int status; + int ret = waitpid(pid, &status, 0); + assert(ret == pid); // should be our child + assert(status == 0); + assert(*shared_val == MAIN_SCOPE_VAL); + } else { + // child adds a callback to the static scope callback manager and then + // exits by returning from main. The parent checks the value after the + // child exits via the memory map. + assert(*shared_val == 0); + int *new_val = (int*)malloc(sizeof(*new_val)); + *new_val = MAIN_SCOPE_VAL; + main_scope_mgr.add_callback(main_scope_cb, new_val); + return 0; + } + + // test exit via exit() + *shared_val = 0; + pid = fork(); + assert(pid >= 0); + if (pid) { + int status; + int ret = waitpid(pid, &status, 0); + assert(ret == pid); // should be our child + assert(WEXITSTATUS(status) == 3); + assert(*shared_val == EXIT_FUNC_VAL); + } else { + // child adds a callback to the static scope callback manager and then + // exits via exit(). + assert(*shared_val == 0); + int *new_val = (int*)malloc(sizeof(*new_val)); + *new_val = EXIT_FUNC_VAL; + exit_func_mgr.add_callback(exit_func_cb, new_val); + call_exit(); + ceph_abort(); + } + + return 0; +}