#include <sys/wait.h>
#include <dlfcn.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <atf-c.h>
#define ARBITRARY_EXIT_CODE 42
static char *
get_shlib(const char *srcdir)
{
char *shlib;
shlib = NULL;
if (asprintf(&shlib, "%s/libatexit.so", srcdir) < 0)
atf_tc_fail("failed to construct path to libatexit.so");
return (shlib);
}
static void
run_test(const atf_tc_t *tc, bool with_fatal_atexit, bool with_exit)
{
pid_t p;
void (*set_fatal_atexit)(bool);
void (*set_exit_code)(int);
void *hdl;
char *shlib;
shlib = get_shlib(atf_tc_get_config_var(tc, "srcdir"));
hdl = dlopen(shlib, RTLD_LAZY);
ATF_REQUIRE_MSG(hdl != NULL, "dlopen: %s", dlerror());
free(shlib);
if (with_fatal_atexit) {
set_fatal_atexit = dlsym(hdl, "set_fatal_atexit");
ATF_REQUIRE_MSG(set_fatal_atexit != NULL,
"set_fatal_atexit: %s", dlerror());
}
if (with_exit) {
set_exit_code = dlsym(hdl, "set_exit_code");
ATF_REQUIRE_MSG(set_exit_code != NULL, "set_exit_code: %s",
dlerror());
}
p = atf_utils_fork();
if (p == 0) {
closefrom(3);
if (with_fatal_atexit)
set_fatal_atexit(true);
if (with_exit)
set_exit_code(ARBITRARY_EXIT_CODE);
dlclose(hdl);
if (with_exit)
exit(1);
exit(0);
}
dlclose(hdl);
atf_utils_wait(p, with_exit ? ARBITRARY_EXIT_CODE : 0, "", "");
}
ATF_TC_WITHOUT_HEAD(simple_cxa_atexit);
ATF_TC_BODY(simple_cxa_atexit, tc)
{
run_test(tc, false, true);
}
ATF_TC_WITHOUT_HEAD(late_cxa_atexit);
ATF_TC_BODY(late_cxa_atexit, tc)
{
run_test(tc, true, false);
}
ATF_TC_WITHOUT_HEAD(late_cxa_atexit_ran);
ATF_TC_BODY(late_cxa_atexit_ran, tc)
{
run_test(tc, true, true);
}
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, simple_cxa_atexit);
ATF_TP_ADD_TC(tp, late_cxa_atexit);
ATF_TP_ADD_TC(tp, late_cxa_atexit_ran);
return (atf_no_error());
}