This is an automated email from the ASF dual-hosted git repository.

bbannier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mesos.git

commit f1789b0fe5cad221b79a0bc2adfe2036cce6f33d
Author: Benjamin Bannier <bbann...@apache.org>
AuthorDate: Wed Sep 25 23:01:24 2019 +0200

    Introduced automatic lifecycle management in `DynamicLibrary`.
    
    This not only simplifies our implementation of `DynamicLibrary`, but
    also removes the potential for accidental file descriptor leaks.
    
    Review: https://reviews.apache.org/r/71388/
---
 .../stout/include/stout/posix/dynamiclibrary.hpp   | 35 ++++++++++++----------
 1 file changed, 19 insertions(+), 16 deletions(-)

diff --git a/3rdparty/stout/include/stout/posix/dynamiclibrary.hpp 
b/3rdparty/stout/include/stout/posix/dynamiclibrary.hpp
index 6a50592..2e2726e 100644
--- a/3rdparty/stout/include/stout/posix/dynamiclibrary.hpp
+++ b/3rdparty/stout/include/stout/posix/dynamiclibrary.hpp
@@ -15,6 +15,7 @@
 
 #include <dlfcn.h>
 
+#include <memory>
 #include <string>
 
 #include <stout/nothing.hpp>
@@ -28,20 +29,17 @@
 class DynamicLibrary
 {
 public:
-  DynamicLibrary() : handle_(nullptr) { }
+  DynamicLibrary()
+    : handle_(nullptr, [](void* handle) {
+        if (handle == nullptr) {
+          return 0;
+        }
 
-  // Since this class manages a naked handle it cannot be copy- or
-  // move-constructed.
-  // TODO(bbannier): Allow for move-construction.
-  DynamicLibrary(const DynamicLibrary&) = delete;
-  DynamicLibrary(DynamicLibrary&&) = delete;
+        return dlclose(handle);
+      })
+  {}
 
-  virtual ~DynamicLibrary()
-  {
-    if (handle_ != nullptr) {
-      close();
-    }
-  }
+  virtual ~DynamicLibrary() = default;
 
   Try<Nothing> open(const std::string& path)
   {
@@ -50,7 +48,7 @@ public:
       return Error("Library already opened");
     }
 
-    handle_ = dlopen(path.c_str(), RTLD_NOW);
+    handle_.reset(dlopen(path.c_str(), RTLD_NOW));
 
     if (handle_ == nullptr) {
       return Error("Could not load library '" + path + "': " + dlerror());
@@ -67,12 +65,17 @@ public:
       return Error("Could not close library; handle was already `nullptr`");
     }
 
-    if (dlclose(handle_) != 0) {
+    if (dlclose(handle_.get()) != 0) {
       return Error(
           "Could not close library '" +
           (path_.isSome() ? path_.get() : "") + "': " + dlerror());
     }
 
+    // Release the handle so the default `dlclose` operation is not
+    // invoked anymore as after successful explicit `dlclose` it does
+    // not point to an open shared object anymore.
+    handle_.release();
+
     handle_ = nullptr;
     path_ = None();
 
@@ -86,7 +89,7 @@ public:
           "Could not get symbol '" + name + "'; library handle was `nullptr`");
     }
 
-    void* symbol = dlsym(handle_, name.c_str());
+    void* symbol = dlsym(handle_.get(), name.c_str());
 
     if (symbol == nullptr) {
       return Error(
@@ -98,7 +101,7 @@ public:
   }
 
 private:
-  void* handle_;
+  std::unique_ptr<void, int (*)(void*)> handle_;
   Option<std::string> path_;
 };
 

Reply via email to