[llvm] r304720 - Close DynamicLibraries in reverse order they were opened.

Frederich Munch via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 5 09:26:58 PDT 2017


Author: marsupial
Date: Mon Jun  5 11:26:58 2017
New Revision: 304720

URL: http://llvm.org/viewvc/llvm-project?rev=304720&view=rev
Log:
Close DynamicLibraries in reverse order they were opened.

Summary: Matches C++ destruction ordering better and fixes possible problems of loaded libraries having inter-dependencies.

Reviewers: efriedma, v.g.vassilev, chapuni

Reviewed By: efriedma

Subscribers: mgorny, llvm-commits

Differential Revision: https://reviews.llvm.org/D33652

Modified:
    llvm/trunk/lib/Support/Unix/DynamicLibrary.inc
    llvm/trunk/lib/Support/Windows/DynamicLibrary.inc
    llvm/trunk/unittests/Support/DynamicLibrary/CMakeLists.txt
    llvm/trunk/unittests/Support/DynamicLibrary/DynamicLibraryTest.cpp
    llvm/trunk/unittests/Support/DynamicLibrary/PipSqueak.cxx
    llvm/trunk/unittests/Support/DynamicLibrary/PipSqueak.h

Modified: llvm/trunk/lib/Support/Unix/DynamicLibrary.inc
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Unix/DynamicLibrary.inc?rev=304720&r1=304719&r2=304720&view=diff
==============================================================================
--- llvm/trunk/lib/Support/Unix/DynamicLibrary.inc (original)
+++ llvm/trunk/lib/Support/Unix/DynamicLibrary.inc Mon Jun  5 11:26:58 2017
@@ -15,7 +15,8 @@
 #include <dlfcn.h>
 
 DynamicLibrary::HandleSet::~HandleSet() {
-  for (void *Handle : Handles)
+  // Close the libraries in reverse order.
+  for (void *Handle : llvm::reverse(Handles))
     ::dlclose(Handle);
   if (Process)
     ::dlclose(Process);

Modified: llvm/trunk/lib/Support/Windows/DynamicLibrary.inc
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Windows/DynamicLibrary.inc?rev=304720&r1=304719&r2=304720&view=diff
==============================================================================
--- llvm/trunk/lib/Support/Windows/DynamicLibrary.inc (original)
+++ llvm/trunk/lib/Support/Windows/DynamicLibrary.inc Mon Jun  5 11:26:58 2017
@@ -23,7 +23,7 @@
 
 
 DynamicLibrary::HandleSet::~HandleSet() {
-  for (void *Handle : Handles)
+  for (void *Handle : llvm::reverse(Handles))
     FreeLibrary(HMODULE(Handle));
 
   // 'Process' should not be released on Windows.

Modified: llvm/trunk/unittests/Support/DynamicLibrary/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Support/DynamicLibrary/CMakeLists.txt?rev=304720&r1=304719&r2=304720&view=diff
==============================================================================
--- llvm/trunk/unittests/Support/DynamicLibrary/CMakeLists.txt (original)
+++ llvm/trunk/unittests/Support/DynamicLibrary/CMakeLists.txt Mon Jun  5 11:26:58 2017
@@ -4,16 +4,21 @@ add_llvm_unittest(DynamicLibraryTests Dy
 
 export_executable_symbols(DynamicLibraryTests)
 
-add_library(PipSqueak SHARED PipSqueak.cxx)
+function(dynlib_add_module NAME)
+  add_library(${NAME} SHARED PipSqueak.cxx)
 
-set_output_directory(PipSqueak
-  BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}
-  LIBRARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}
-  )
-
-set_target_properties(PipSqueak
-  PROPERTIES PREFIX ""
-  SUFFIX ".so"
-  )
+  set_output_directory(${NAME}
+    BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}
+    LIBRARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}
+    )
 
-add_dependencies(DynamicLibraryTests PipSqueak)
+  set_target_properties(${NAME}
+    PROPERTIES PREFIX ""
+    SUFFIX ".so"
+    )
+
+  add_dependencies(DynamicLibraryTests ${NAME})
+endfunction(dynlib_add_module)
+
+dynlib_add_module(PipSqueak)
+dynlib_add_module(SecondLib)

Modified: llvm/trunk/unittests/Support/DynamicLibrary/DynamicLibraryTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Support/DynamicLibrary/DynamicLibraryTest.cpp?rev=304720&r1=304719&r2=304720&view=diff
==============================================================================
--- llvm/trunk/unittests/Support/DynamicLibrary/DynamicLibraryTest.cpp (original)
+++ llvm/trunk/unittests/Support/DynamicLibrary/DynamicLibraryTest.cpp Mon Jun  5 11:26:58 2017
@@ -15,26 +15,26 @@
 #include "gtest/gtest.h"
 
 #include "PipSqueak.h"
-#include <string>
 
 using namespace llvm;
 using namespace llvm::sys;
 
 extern "C" PIPSQUEAK_EXPORT const char *TestA() { return "ProcessCall"; }
 
-std::string LibPath() {
+std::string LibPath(const std::string Name = "PipSqueak") {
   const std::vector<testing::internal::string>& Argvs = testing::internal::GetArgvs();
   const char *Argv0 = Argvs.size() > 0 ? Argvs[0].c_str() : "DynamicLibraryTests";
   void *Ptr = (void*)(intptr_t)TestA;
   std::string Path = fs::getMainExecutable(Argv0, Ptr);
   llvm::SmallString<256> Buf(path::parent_path(Path));
-  path::append(Buf, "PipSqueak.so");
+  path::append(Buf, (Name+".so").c_str());
   return Buf.str();
 }
 
 #if defined(_WIN32) || (defined(HAVE_DLFCN_H) && defined(HAVE_DLOPEN))
 
 typedef void (*SetStrings)(std::string &GStr, std::string &LStr);
+typedef void (*TestOrder)(std::vector<std::string> &V);
 typedef const char *(*GetString)();
 
 template <class T> static T FuncPtr(void *Ptr) {
@@ -100,26 +100,59 @@ TEST(DynamicLibrary, Overload) {
 }
 
 TEST(DynamicLibrary, Shutdown) {
-  std::string A, B;
+  std::string A("PipSqueak"), B, C("SecondLib");
+  std::vector<std::string> Order;
   {
     std::string Err;
     llvm_shutdown_obj Shutdown;
     DynamicLibrary DL =
-        DynamicLibrary::getPermanentLibrary(LibPath().c_str(), &Err);
+        DynamicLibrary::getPermanentLibrary(LibPath(A).c_str(), &Err);
     EXPECT_TRUE(DL.isValid());
     EXPECT_TRUE(Err.empty());
 
-    SetStrings SS = FuncPtr<SetStrings>(
+    SetStrings SS_0 = FuncPtr<SetStrings>(
+        DynamicLibrary::SearchForAddressOfSymbol("SetStrings"));
+    EXPECT_TRUE(SS_0 != nullptr);
+
+    SS_0(A, B);
+    EXPECT_EQ(B, "Local::Local(PipSqueak)");
+
+    TestOrder TO_0 = FuncPtr<TestOrder>(
+        DynamicLibrary::SearchForAddressOfSymbol("TestOrder"));
+    EXPECT_TRUE(TO_0 != nullptr);
+    
+    DynamicLibrary DL2 =
+        DynamicLibrary::getPermanentLibrary(LibPath(C).c_str(), &Err);
+    EXPECT_TRUE(DL2.isValid());
+    EXPECT_TRUE(Err.empty());
+
+    // Should find latest version of symbols in SecondLib
+    SetStrings SS_1 = FuncPtr<SetStrings>(
         DynamicLibrary::SearchForAddressOfSymbol("SetStrings"));
-    EXPECT_TRUE(SS != nullptr);
+    EXPECT_TRUE(SS_1 != nullptr);
+    EXPECT_TRUE(SS_0 != SS_1);
 
-    SS(A, B);
-    EXPECT_EQ(B, "Local::Local");
+    TestOrder TO_1 = FuncPtr<TestOrder>(
+        DynamicLibrary::SearchForAddressOfSymbol("TestOrder"));
+    EXPECT_TRUE(TO_1 != nullptr);
+    EXPECT_TRUE(TO_0 != TO_1);
+
+    B.clear();
+    SS_1(C, B);
+    EXPECT_EQ(B, "Local::Local(SecondLib)");
+
+    TO_0(Order);
+    TO_1(Order);
   }
   EXPECT_EQ(A, "Global::~Global");
   EXPECT_EQ(B, "Local::~Local");
   EXPECT_TRUE(FuncPtr<SetStrings>(DynamicLibrary::SearchForAddressOfSymbol(
                   "SetStrings")) == nullptr);
+
+  // Test unload/destruction ordering
+  EXPECT_EQ(Order.size(), 2UL);
+  EXPECT_EQ(Order.front(), "SecondLib");
+  EXPECT_EQ(Order.back(), "PipSqueak");
 }
 
 #else

Modified: llvm/trunk/unittests/Support/DynamicLibrary/PipSqueak.cxx
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Support/DynamicLibrary/PipSqueak.cxx?rev=304720&r1=304719&r2=304720&view=diff
==============================================================================
--- llvm/trunk/unittests/Support/DynamicLibrary/PipSqueak.cxx (original)
+++ llvm/trunk/unittests/Support/DynamicLibrary/PipSqueak.cxx Mon Jun  5 11:26:58 2017
@@ -9,38 +9,40 @@
 
 #include "PipSqueak.h"
 
-#if defined(_WIN32) && !defined(__GNUC__)
-// Disable warnings from inclusion of xlocale & exception
-#pragma warning(push)
-#pragma warning(disable: 4530)
-#pragma warning(disable: 4577)
-#include <string>
-#pragma warning(pop)
-#else
-#include <string>
-#endif
-
 struct Global {
   std::string *Str;
-  Global() : Str(nullptr) {}
+  std::vector<std::string> *Vec;
+  Global() : Str(nullptr), Vec(nullptr) {}
   ~Global() {
-    if (Str)
+    if (Str) {
+      if (Vec)
+        Vec->push_back(*Str);
       *Str = "Global::~Global";
+    }
   }
 };
 
+static Global Glb;
+
 struct Local {
   std::string &Str;
-  Local(std::string &S) : Str(S) { Str = "Local::Local"; }
+  Local(std::string &S) : Str(S) {
+    Str = "Local::Local";
+    if (Glb.Str && !Glb.Str->empty())
+      Str += std::string("(") + *Glb.Str + std::string(")");
+  }
   ~Local() { Str = "Local::~Local"; }
 };
 
-static Global Glb;
 
 extern "C" PIPSQUEAK_EXPORT void SetStrings(std::string &GStr,
                                             std::string &LStr) {
-  static Local Lcl(LStr);
   Glb.Str = &GStr;
+  static Local Lcl(LStr);
+}
+
+extern "C" PIPSQUEAK_EXPORT void TestOrder(std::vector<std::string> &V) {
+  Glb.Vec = &V;
 }
 
 extern "C" PIPSQUEAK_EXPORT const char *TestA() { return "LibCall"; }

Modified: llvm/trunk/unittests/Support/DynamicLibrary/PipSqueak.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Support/DynamicLibrary/PipSqueak.h?rev=304720&r1=304719&r2=304720&view=diff
==============================================================================
--- llvm/trunk/unittests/Support/DynamicLibrary/PipSqueak.h (original)
+++ llvm/trunk/unittests/Support/DynamicLibrary/PipSqueak.h Mon Jun  5 11:26:58 2017
@@ -10,6 +10,19 @@
 #ifndef LLVM_PIPSQUEAK_H
 #define LLVM_PIPSQUEAK_H
 
+#if defined(_WIN32) && !defined(__GNUC__)
+// Disable warnings from inclusion of xlocale & exception
+#pragma warning(push)
+#pragma warning(disable: 4530)
+#pragma warning(disable: 4577)
+#include <string>
+#include <vector>
+#pragma warning(pop)
+#else
+#include <string>
+#include <vector>
+#endif
+
 #ifdef _WIN32
 #define PIPSQUEAK_EXPORT __declspec(dllexport)
 #else




More information about the llvm-commits mailing list