1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 // To work around b/25643775, we disable clang optimization so that 18 // VTT for std::__1::basic_stringstream<char, std::__1::char_traits<char>, 19 // std::__1::allocator<char> > 20 // will be correctly kept for other module's references. 21 #if defined(__clang__) && (defined(__arm__) || defined(__aarch64__)) 22 #pragma clang optimize off 23 #endif 24 #include <gtest/gtest.h> 25 #if defined(__clang__) && (defined(__arm__) || defined(__aarch64__)) 26 #pragma clang optimize on 27 #endif 28 29 #include <dlfcn.h> 30 #include <libgen.h> 31 #include <limits.h> 32 #include <stdio.h> 33 #include <stdint.h> 34 35 #include <string> 36 37 TEST(atexit, sofile) { 38 std::string atexit_call_sequence; 39 bool valid_this_in_static_dtor = false; 40 bool attr_dtor_called = false; 41 42 void* handle = dlopen("libtest_atexit.so", RTLD_NOW); 43 ASSERT_TRUE(handle != nullptr); 44 45 typedef int (*int_fn)(void); 46 int_fn get_cxx_ctor_called, get_attr_ctor_called; 47 get_cxx_ctor_called = reinterpret_cast<int_fn>(dlsym(handle, "get_cxx_ctor_called")); 48 get_attr_ctor_called = reinterpret_cast<int_fn>(dlsym(handle, "get_attr_ctor_called")); 49 ASSERT_TRUE(get_cxx_ctor_called != nullptr); 50 ASSERT_TRUE(get_attr_ctor_called != nullptr); 51 52 ASSERT_EQ(1, get_cxx_ctor_called()); 53 ASSERT_EQ(1, get_attr_ctor_called()); 54 55 void* sym = dlsym(handle, "register_atexit"); 56 ASSERT_TRUE(sym != nullptr); 57 reinterpret_cast<void (*)(std::string*, bool*, bool*)>(sym)(&atexit_call_sequence, &valid_this_in_static_dtor, &attr_dtor_called); 58 59 ASSERT_EQ(0, dlclose(handle)); 60 // this test verifies atexit call from atexit handler. as well as the order of calls 61 ASSERT_EQ("Humpty Dumpty sat on a wall", atexit_call_sequence); 62 ASSERT_TRUE(valid_this_in_static_dtor); 63 ASSERT_TRUE(attr_dtor_called); 64 } 65 66 class TestMainStaticDtorClass { 67 public: 68 TestMainStaticDtorClass() { 69 expected_this = this; 70 } 71 72 ~TestMainStaticDtorClass() { 73 if (this != expected_this) { 74 fprintf(stderr, "\nerror: static d-tor called with incorrect this pointer: %p, expected: %p\n", this, expected_this); 75 } else { 76 fprintf(stderr, "6"); 77 } 78 } 79 private: 80 static const TestMainStaticDtorClass* expected_this; 81 }; 82 83 const TestMainStaticDtorClass* TestMainStaticDtorClass::expected_this = nullptr; 84 85 static void atexit_func5() { 86 fprintf(stderr, "5"); 87 } 88 89 static void atexit_func4() { 90 fprintf(stderr, "4"); 91 } 92 93 static void atexit_func3() { 94 fprintf(stderr, "3"); 95 atexit(atexit_func4); 96 } 97 98 static void atexit_func2() { 99 fprintf(stderr, "2"); 100 } 101 102 static void atexit_func1() { 103 fprintf(stderr, "1"); 104 } 105 106 static void atexit_main() { 107 // This should result in "123456" output to stderr 108 static TestMainStaticDtorClass static_obj; 109 atexit(atexit_func5); 110 atexit(atexit_func3); 111 atexit(atexit_func2); 112 atexit(atexit_func1); 113 exit(0); 114 } 115 116 TEST(atexit, exit) { 117 ASSERT_EXIT(atexit_main(), testing::ExitedWithCode(0), "123456"); 118 } 119 120