1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
#include <opentracing/dynamic_load.h>
#include <opentracing/version.h>
#include <windows.h>
namespace opentracing {
BEGIN_OPENTRACING_ABI_NAMESPACE
// Returns the last Win32 error, in string format. Returns an empty string if
// there is no error.
//
// Taken from https://stackoverflow.com/a/17387176/4447365
static std::string GetLastErrorAsString() {
// Get the error message, if any.
DWORD errorMessageID = ::GetLastError();
if (errorMessageID == 0)
return std::string(); // No error message has been recorded
LPSTR messageBuffer = nullptr;
size_t size = FormatMessageA(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPSTR)&messageBuffer, 0, NULL);
std::string message(messageBuffer, size);
// Free the buffer.
LocalFree(messageBuffer);
return message;
}
namespace {
class DynamicLibraryHandleWindows : public DynamicLibraryHandle {
public:
explicit DynamicLibraryHandleWindows(HINSTANCE handle) : handle_{handle} {}
~DynamicLibraryHandleWindows() override { FreeLibrary(handle_); }
private:
HINSTANCE handle_;
};
} // namespace
expected<DynamicTracingLibraryHandle> DynamicallyLoadTracingLibrary(
const char* shared_library, std::string& error_message) noexcept try {
const auto handle = LoadLibrary(shared_library);
if (handle == nullptr) {
error_message = "An error occurred: " + GetLastErrorAsString();
return make_unexpected(dynamic_load_failure_error);
}
std::unique_ptr<DynamicLibraryHandle> dynamic_library_handle{
new DynamicLibraryHandleWindows{handle}};
const auto make_tracer_factory =
reinterpret_cast<OpenTracingMakeTracerFactoryType**>(
GetProcAddress(handle, "OpenTracingMakeTracerFactory"));
if (make_tracer_factory == nullptr) {
error_message =
"An error occurred while looking up for OpenTracingMakeTracerFactory "
": " +
GetLastErrorAsString();
return make_unexpected(dynamic_load_failure_error);
}
if (*make_tracer_factory == nullptr) {
error_message =
"An error occurred while looking up for OpenTracingMakeTracerFactory. "
"It seems that it was set to nullptr.";
return make_unexpected(dynamic_load_failure_error);
}
const void* error_category = nullptr;
void* tracer_factory = nullptr;
const auto rcode = (*make_tracer_factory)(
OPENTRACING_VERSION, OPENTRACING_ABI_VERSION, &error_category,
static_cast<void*>(&error_message), &tracer_factory);
if (rcode != 0) {
if (error_category == nullptr) {
error_message = "failed to construct a TracerFactory: unknown error code";
return make_unexpected(dynamic_load_failure_error);
}
const auto error_code = std::error_code{
rcode, *static_cast<const std::error_category*>(error_category)};
if (error_message.empty()) {
error_message = error_code.message();
}
return make_unexpected(error_code);
}
if (tracer_factory == nullptr) {
error_message =
"failed to construct a TracerFactory: `tracer_factory` is null";
return make_unexpected(dynamic_load_failure_error);
}
return DynamicTracingLibraryHandle{
std::unique_ptr<const TracerFactory>{
static_cast<TracerFactory*>(tracer_factory)},
std::move(dynamic_library_handle)};
} catch (const std::bad_alloc&) {
return make_unexpected(std::make_error_code(std::errc::not_enough_memory));
}
END_OPENTRACING_ABI_NAMESPACE
} // namespace opentracing
|