From d3eaff2adbcbb09884c5a9a13478f4050fa0c3ac Mon Sep 17 00:00:00 2001
From: Marko Budiselic <marko.budiselic@memgraph.com>
Date: Sat, 8 Apr 2023 11:39:46 +0000
Subject: [PATCH] Move SharedLibraryHandle to utils

---
 src/query/procedure/module.hpp         | 25 +++-----------
 src/utils/shared_library_handle.hpp    | 46 ++++++++++++++++++++++++++
 tests/manual/CMakeLists.txt            |  2 ++
 tests/manual/shared_library_handle.cpp | 30 +++++++++++++++++
 4 files changed, 82 insertions(+), 21 deletions(-)
 create mode 100644 src/utils/shared_library_handle.hpp
 create mode 100644 tests/manual/shared_library_handle.cpp

diff --git a/src/query/procedure/module.hpp b/src/query/procedure/module.hpp
index 82478257b..697caae79 100644
--- a/src/query/procedure/module.hpp
+++ b/src/query/procedure/module.hpp
@@ -1,4 +1,4 @@
-// Copyright 2022 Memgraph Ltd.
+// Copyright 2023 Memgraph Ltd.
 //
 // Use of this software is governed by the Business Source License
 // included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
@@ -26,6 +26,7 @@
 #include "query/procedure/mg_procedure_impl.hpp"
 #include "utils/memory.hpp"
 #include "utils/rw_lock.hpp"
+#include "utils/shared_library_handle.hpp"
 
 class CypherMainVisitorTest;
 
@@ -129,28 +130,10 @@ class ModuleRegistry final {
   const std::filesystem::path &InternalModuleDir() const noexcept;
 
  private:
-  class SharedLibraryHandle {
-   public:
-    SharedLibraryHandle(const std::string &shared_library, int mode) : handle_{dlopen(shared_library.c_str(), mode)} {}
-    SharedLibraryHandle(const SharedLibraryHandle &) = delete;
-    SharedLibraryHandle(SharedLibraryHandle &&) = delete;
-    SharedLibraryHandle operator=(const SharedLibraryHandle &) = delete;
-    SharedLibraryHandle operator=(SharedLibraryHandle &&) = delete;
-
-    ~SharedLibraryHandle() {
-      if (handle_) {
-        dlclose(handle_);
-      }
-    }
-
-   private:
-    void *handle_;
-  };
-
 #if __has_feature(address_sanitizer)
   // This is why we need RTLD_NODELETE and we must not use RTLD_DEEPBIND with
   // ASAN: https://github.com/google/sanitizers/issues/89
-  SharedLibraryHandle libstd_handle{"libstdc++.so.6", RTLD_NOW | RTLD_LOCAL | RTLD_NODELETE};
+  utils::LinuxDLHandle libstd_handle{"libstdc++.so.6", RTLD_NOW | RTLD_LOCAL | RTLD_NODELETE};
 #else
   // The reason behind opening share library during runtime is to avoid issues
   // with loading symbols from stdlib. We have encounter issues with locale
@@ -161,7 +144,7 @@ class ModuleRegistry final {
   // mentioned library will be first performed in the already existing binded
   // libraries and then the global namespace.
   // RTLD_DEEPBIND => https://linux.die.net/man/3/dlopen
-  SharedLibraryHandle libstd_handle{"libstdc++.so.6", RTLD_NOW | RTLD_LOCAL | RTLD_DEEPBIND};
+  utils::LinuxDLHandle libstd_handle{"libstdc++.so.6", RTLD_NOW | RTLD_LOCAL | RTLD_DEEPBIND};
 #endif
   std::vector<std::filesystem::path> modules_dirs_;
   std::filesystem::path internal_module_dir_;
diff --git a/src/utils/shared_library_handle.hpp b/src/utils/shared_library_handle.hpp
new file mode 100644
index 000000000..abf5a4bc2
--- /dev/null
+++ b/src/utils/shared_library_handle.hpp
@@ -0,0 +1,46 @@
+// Copyright 2023 Memgraph Ltd.
+//
+// Use of this software is governed by the Business Source License
+// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
+// License, and you may not use this file except in compliance with the Business Source License.
+//
+// As of the Change Date specified in that file, in accordance with
+// the Business Source License, use of this software will be governed
+// by the Apache License, Version 2.0, included in the file
+// licenses/APL.txt.
+
+#include <string>
+
+// https://stackoverflow.com/questions/142508/how-do-i-check-os-with-a-preprocessor-directive
+// TODO(gitbuda): Deal with the flags in both: OS case and ASAN case.
+
+namespace memgraph::utils {
+
+#if defined(__linux__) || defined(__APPLE__)
+#include <dlfcn.h>
+
+class LinuxDLHandle {
+ public:
+  LinuxDLHandle(const std::string &shared_library, int mode) : handle_{dlopen(shared_library.c_str(), mode)} {}
+  LinuxDLHandle(const LinuxDLHandle &) = delete;
+  LinuxDLHandle(LinuxDLHandle &&) = delete;
+  LinuxDLHandle operator=(const LinuxDLHandle &) = delete;
+  LinuxDLHandle operator=(LinuxDLHandle &&) = delete;
+
+  ~LinuxDLHandle() {
+    if (handle_) {
+      dlclose(handle_);
+    }
+  }
+
+ private:
+  void *handle_;
+};
+#endif
+
+#ifdef _WIN32
+#include <windows.h>
+class WindowsDLLHandle {};
+#endif
+
+}  // namespace memgraph::utils
diff --git a/tests/manual/CMakeLists.txt b/tests/manual/CMakeLists.txt
index 0a46b8e60..5547b61b6 100644
--- a/tests/manual/CMakeLists.txt
+++ b/tests/manual/CMakeLists.txt
@@ -55,3 +55,5 @@ target_link_libraries(${test_prefix}ssl_client mg-communication)
 
 add_manual_test(ssl_server.cpp)
 target_link_libraries(${test_prefix}ssl_server mg-communication)
+
+add_manual_test(shared_library_handle.cpp)
diff --git a/tests/manual/shared_library_handle.cpp b/tests/manual/shared_library_handle.cpp
new file mode 100644
index 000000000..a75d5ee5f
--- /dev/null
+++ b/tests/manual/shared_library_handle.cpp
@@ -0,0 +1,30 @@
+// Copyright 2023 Memgraph Ltd.
+//
+// Use of this software is governed by the Business Source License
+// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
+// License, and you may not use this file except in compliance with the Business Source License.
+//
+// As of the Change Date specified in that file, in accordance with
+// the Business Source License, use of this software will be governed
+// by the Apache License, Version 2.0, included in the file
+// licenses/APL.txt.
+
+#include <iostream>
+
+#include "utils/shared_library_handle.hpp"
+
+using namespace memgraph::utils;
+
+int main(int argc, char *argv[]) {
+#if defined(__linux__)
+  LinuxDLHandle handle("test", 0);
+#elif defined(__APPLE__)
+  LinuxDLHandle handle("test", 0);
+#elif defined(_WIN32)
+  WindowsDLLHandle handle("test", 0);
+#else
+  std::cout << "Unsupportd platform" << std::end;
+#endif
+
+  return 0;
+}