Path: blob/main/lib/libc/tests/stdlib/cxa_thread_atexit_test.cc
39530 views
/*-1* Copyright (c) 2016 Mahdi Mokhtari <[email protected]>2* All rights reserved.3*4* Redistribution and use in source and binary forms, with or without5* modification, are permitted provided that the following conditions6* are met:7* 1. Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer.9* 2. Redistributions in binary form must reproduce the above copyright10* notice, this list of conditions and the following disclaimer in the11* documentation and/or other materials provided with the distribution.12*13* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND14* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE15* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE16* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE17* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL18* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS19* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)20* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT21* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY22* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF23* SUCH DAMAGE.24*/2526#include <dlfcn.h>27#include <atf-c++.hpp>28#include <cstdio>29#include <cstdlib>30#include <thread>3132static FILE *output = NULL;3334struct Foo {35Foo() { ATF_REQUIRE(fprintf(output, "Created\n") > 0); }36~Foo() { ATF_REQUIRE(fprintf(output, "Destroyed\n") > 0); }37void use() { ATF_REQUIRE(fprintf(output, "Used\n") > 0); }38};3940struct Bar {41Bar() {}42~Bar() {43thread_local static Foo foo;44ATF_REQUIRE(fprintf(output, "DIED\n") > 0);45}46void use() {}47};4849extern "C" int __cxa_thread_atexit(void (*)(void *), void *, void *);5051static void52again(void *arg)53{5455__cxa_thread_atexit(again, arg, &output);56}5758struct Baz {59Baz() {}60~Baz() {61again(NULL);62}63void use() {}64};6566static thread_local Foo f;67static thread_local Foo g;68static thread_local Bar h;69static thread_local Baz e;7071/*72* This test must be linked to libpthread.73*/74ATF_TEST_CASE_WITHOUT_HEAD(cxx__thr);75ATF_TEST_CASE_BODY(cxx__thr)76{77void *libthr_handle;7879/* Avoid coredump during f construction. */80output = stderr;8182libthr_handle = dlopen("libthr.so.3", RTLD_LAZY | RTLD_GLOBAL |83RTLD_NOLOAD);84ATF_REQUIRE(libthr_handle != NULL);85dlclose(libthr_handle);86}8788/*89* In this test f.use() will test cxa_thread_atexit() in non-threaded mode.90* After f.use() main will be threaded and we'll have one additional thread91* with its own TLS data.92*/93ATF_TEST_CASE_WITHOUT_HEAD(cxx__thread_local_before);94ATF_TEST_CASE_BODY(cxx__thread_local_before)95{96static const char out_log[] = "Created\nCreated\nUsed\nCreated\n"97"Created\nUsed\nCreated\nDIED\nDestroyed\nDestroyed\nDestroyed\n";9899ATF_REQUIRE((output = fopen("test_before.txt", "w")) != NULL);100101f.use();102std::thread t([]() { f.use(); });103t.join();104105fflush(output);106107ATF_REQUIRE(atf::utils::compare_file("test_before.txt", out_log));108}109110/*111* In this test, f.use() will test __cxa_thread_atexit()112* in threaded mode (but still in main-threaed).113*/114ATF_TEST_CASE_WITHOUT_HEAD(cxx__thread_local_after);115ATF_TEST_CASE_BODY(cxx__thread_local_after)116{117static const char out_log[] = "Created\nCreated\nUsed\nCreated\n"118"DIED\nDestroyed\nDestroyed\nDestroyed\nCreated\nCreated\nUsed\n";119120ATF_REQUIRE((output = fopen("test_after.txt", "w")) != NULL);121122std::thread t([]() { g.use(); });123t.join();124sleep(1);125g.use();126127fflush(output);128129ATF_REQUIRE(atf::utils::compare_file("test_after.txt", out_log));130}131132/*133* In this test, we register a new dtor while dtors are being run134* in __cxa_thread_atexit().135*/136ATF_TEST_CASE_WITHOUT_HEAD(cxx__thread_local_add_while_calling_dtors);137ATF_TEST_CASE_BODY(cxx__thread_local_add_while_calling_dtors)138{139static const char out_log[] = "Created\nCreated\nCreated\nDIED\n"140"Destroyed\nDestroyed\nDestroyed\n";141142ATF_REQUIRE((output = fopen("test_add_meanwhile.txt", "w")) != NULL);143144std::thread t([]() { h.use(); });145t.join();146sleep(1);147148fflush(output);149150ATF_REQUIRE(atf::utils::compare_file("test_add_meanwhile.txt", out_log));151}152153ATF_TEST_CASE_WITHOUT_HEAD(cxx__thread_inf_dtors);154ATF_TEST_CASE_BODY(cxx__thread_inf_dtors)155{156157/*158* Only added to make isolated run of this test not159* coredumping. Construction of Foo objects require filled160* output.161*/162output = stderr;163164std::thread t([]() { e.use(); });165t.join();166}167168ATF_INIT_TEST_CASES(tcs)169{170171ATF_ADD_TEST_CASE(tcs, cxx__thr);172ATF_ADD_TEST_CASE(tcs, cxx__thread_local_before);173ATF_ADD_TEST_CASE(tcs, cxx__thread_local_after);174ATF_ADD_TEST_CASE(tcs, cxx__thread_local_add_while_calling_dtors);175ATF_ADD_TEST_CASE(tcs, cxx__thread_inf_dtors);176}177178179