loader: fix d-tor call order
In the case when there are multiple dependencies on
the same library in the local_group the unload may
in some situations (covered now by tests) result
calling d-tors for some libraries prematurely.
In order to have correct call order loader checks if this
is last dependency in local group before adding it to BFS
queue.
Bug: http://b/35201832
Test: bionic-unit-tests --gtest_filter=dl*:Dl*
Test: bionic-unit-tests-glibc --gtest_filter=dl*
Change-Id: I4c6955b9032acc7147a51d9f09b61d9e0818700c
diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp
index 3e9e85e..48fb6d1 100644
--- a/tests/dlfcn_test.cpp
+++ b/tests/dlfcn_test.cpp
@@ -1142,8 +1142,9 @@
g_fini_call_order_str += s;
}
-TEST(dlfcn, init_fini_call_order) {
- void* handle = dlopen("libtest_init_fini_order_root.so", RTLD_NOW);
+static void test_init_fini_call_order_for(const char* libname) {
+ g_fini_call_order_str.clear();
+ void* handle = dlopen(libname, RTLD_NOW);
ASSERT_TRUE(handle != nullptr) << dlerror();
typedef int (*get_init_order_number_t)();
get_init_order_number_t get_init_order_number =
@@ -1158,6 +1159,11 @@
ASSERT_EQ("(root)(child)(grandchild)", g_fini_call_order_str);
}
+TEST(dlfcn, init_fini_call_order) {
+ test_init_fini_call_order_for("libtest_init_fini_order_root.so");
+ test_init_fini_call_order_for("libtest_init_fini_order_root2.so");
+}
+
TEST(dlfcn, symbol_versioning_use_v1) {
void* handle = dlopen("libtest_versioned_uselibv1.so", RTLD_NOW);
ASSERT_TRUE(handle != nullptr) << dlerror();
diff --git a/tests/libs/Android.bp b/tests/libs/Android.bp
index 31a0916..5eb16c5 100644
--- a/tests/libs/Android.bp
+++ b/tests/libs/Android.bp
@@ -448,13 +448,26 @@
}
// -----------------------------------------------------------------------------
-// Library used to check init/fini call order
+// Libraries used to check init/fini call order
// -----------------------------------------------------------------------------
cc_test_library {
name: "libtest_init_fini_order_root",
defaults: ["bionic_testlib_defaults"],
srcs: ["dlopen_check_init_fini_root.cpp"],
- shared_libs: ["libtest_init_fini_order_child"],
+ shared_libs: [
+ "libtest_init_fini_order_child",
+ "libtest_init_fini_order_grand_child",
+ ],
+}
+
+cc_test_library {
+ name: "libtest_init_fini_order_root2",
+ defaults: ["bionic_testlib_defaults"],
+ srcs: ["dlopen_check_init_fini_root.cpp"],
+ shared_libs: [
+ "libtest_init_fini_order_grand_child",
+ "libtest_init_fini_order_child",
+ ],
}
cc_test_library {