dynamic_load_unix.h 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. // Copyright The OpenTelemetry Authors
  2. // SPDX-License-Identifier: Apache-2.0
  3. #pragma once
  4. #include <dlfcn.h>
  5. #include <algorithm>
  6. #include <memory>
  7. #include "opentelemetry/plugin/detail/dynamic_library_handle.h"
  8. #include "opentelemetry/plugin/detail/loader_info.h"
  9. #include "opentelemetry/plugin/detail/utility.h"
  10. #include "opentelemetry/plugin/factory.h"
  11. #include "opentelemetry/plugin/hook.h"
  12. #include "opentelemetry/version.h"
  13. OPENTELEMETRY_BEGIN_NAMESPACE
  14. namespace plugin
  15. {
  16. class DynamicLibraryHandleUnix final : public DynamicLibraryHandle
  17. {
  18. public:
  19. explicit DynamicLibraryHandleUnix(void *handle) noexcept : handle_{handle} {}
  20. ~DynamicLibraryHandleUnix() override { ::dlclose(handle_); }
  21. private:
  22. void *handle_;
  23. };
  24. inline std::unique_ptr<Factory> LoadFactory(const char *plugin, std::string &error_message) noexcept
  25. {
  26. dlerror(); // Clear any existing error.
  27. auto handle = ::dlopen(plugin, RTLD_NOW | RTLD_LOCAL);
  28. if (handle == nullptr)
  29. {
  30. detail::CopyErrorMessage(dlerror(), error_message);
  31. return nullptr;
  32. }
  33. std::shared_ptr<DynamicLibraryHandle> library_handle{new (std::nothrow)
  34. DynamicLibraryHandleUnix{handle}};
  35. if (library_handle == nullptr)
  36. {
  37. return nullptr;
  38. }
  39. auto make_factory_impl =
  40. reinterpret_cast<OpenTelemetryHook *>(::dlsym(handle, "OpenTelemetryMakeFactoryImpl"));
  41. if (make_factory_impl == nullptr)
  42. {
  43. detail::CopyErrorMessage(dlerror(), error_message);
  44. return nullptr;
  45. }
  46. if (*make_factory_impl == nullptr)
  47. {
  48. detail::CopyErrorMessage("Invalid plugin hook", error_message);
  49. return nullptr;
  50. }
  51. LoaderInfo loader_info;
  52. nostd::unique_ptr<char[]> plugin_error_message;
  53. auto factory_impl = (**make_factory_impl)(loader_info, plugin_error_message);
  54. if (factory_impl == nullptr)
  55. {
  56. detail::CopyErrorMessage(plugin_error_message.get(), error_message);
  57. return nullptr;
  58. }
  59. return std::unique_ptr<Factory>{new (std::nothrow)
  60. Factory{std::move(library_handle), std::move(factory_impl)}};
  61. }
  62. } // namespace plugin
  63. OPENTELEMETRY_END_NAMESPACE