Skip to content

Commit f2909db

Browse files
feat: load additional dependencies without modifying PATH (#428)
1 parent f503082 commit f2909db

File tree

6 files changed

+154
-119
lines changed

6 files changed

+154
-119
lines changed

src/backend_manager.cc

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "backend_manager.h"
2828

2929
#include <algorithm>
30+
#include <vector>
3031

3132
#include "backend_memory_manager.h"
3233
#include "server_message.h"
@@ -96,12 +97,14 @@ TritonBackend::Create(
9697
if (local_backend->backend_init_fn_ != nullptr) {
9798
std::unique_ptr<SharedLibrary> slib;
9899
RETURN_IF_ERROR(SharedLibrary::Acquire(&slib));
99-
RETURN_IF_ERROR(slib->SetLibraryDirectory(local_backend->dir_));
100+
void* directory_cookie = nullptr;
101+
RETURN_IF_ERROR(
102+
slib->AddLibraryDirectory(local_backend->dir_, &directory_cookie));
100103

101104
TRITONSERVER_Error* err = local_backend->backend_init_fn_(
102105
reinterpret_cast<TRITONBACKEND_Backend*>(local_backend.get()));
103106

104-
RETURN_IF_ERROR(slib->ResetLibraryDirectory());
107+
RETURN_IF_ERROR(slib->RemoveLibraryDirectory(directory_cookie));
105108
RETURN_IF_TRITONSERVER_ERROR(err);
106109
}
107110

@@ -192,18 +195,13 @@ TritonBackend::LoadBackendLibrary(
192195
std::unique_ptr<SharedLibrary> slib;
193196
RETURN_IF_ERROR(SharedLibrary::Acquire(&slib));
194197

195-
std::wstring original_path;
196198
if (!additional_dependency_dir_path.empty()) {
197-
RETURN_IF_ERROR(slib->AddAdditionalDependencyDir(
198-
additional_dependency_dir_path, original_path));
199+
RETURN_IF_ERROR(
200+
slib->SetAdditionalDependencyDirs(additional_dependency_dir_path));
199201
}
200202

201203
RETURN_IF_ERROR(slib->OpenLibraryHandle(libpath_, &dlhandle_));
202204

203-
if (!additional_dependency_dir_path.empty()) {
204-
RETURN_IF_ERROR(slib->RemoveAdditionalDependencyDir(original_path));
205-
}
206-
207205
// Backend initialize and finalize functions, optional
208206
RETURN_IF_ERROR(slib->GetEntrypoint(
209207
dlhandle_, "TRITONBACKEND_Initialize", true /* optional */,

src/backend_model.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,14 +163,16 @@ TritonModel::Create(
163163
#ifdef _WIN32
164164
std::unique_ptr<SharedLibrary> slib;
165165
RETURN_IF_ERROR(SharedLibrary::Acquire(&slib));
166-
RETURN_IF_ERROR(slib->SetLibraryDirectory(backend->Directory()));
166+
void* directory_cookie = nullptr;
167+
RETURN_IF_ERROR(
168+
slib->AddLibraryDirectory(backend->Directory(), &directory_cookie));
167169
#endif
168170

169171
TRITONSERVER_Error* err = backend->ModelInitFn()(
170172
reinterpret_cast<TRITONBACKEND_Model*>(raw_local_model));
171173

172174
#ifdef _WIN32
173-
RETURN_IF_ERROR(slib->ResetLibraryDirectory());
175+
RETURN_IF_ERROR(slib->RemoveLibraryDirectory(directory_cookie));
174176
#endif
175177
RETURN_IF_TRITONSERVER_ERROR(err);
176178
}

src/backend_model_instance.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -300,14 +300,16 @@ TritonModelInstance::ConstructAndInitializeInstance(
300300
#ifdef _WIN32
301301
std::unique_ptr<SharedLibrary> slib;
302302
RETURN_IF_ERROR(SharedLibrary::Acquire(&slib));
303-
RETURN_IF_ERROR(slib->SetLibraryDirectory(model->Backend()->Directory()));
303+
void* directory_cookie = nullptr;
304+
RETURN_IF_ERROR(slib->AddLibraryDirectory(
305+
model->Backend()->Directory(), &directory_cookie));
304306
#endif
305307

306308
TRITONSERVER_Error* err =
307309
model->Backend()->ModelInstanceInitFn()(triton_instance);
308310

309311
#ifdef _WIN32
310-
RETURN_IF_ERROR(slib->ResetLibraryDirectory());
312+
RETURN_IF_ERROR(slib->RemoveLibraryDirectory(directory_cookie));
311313
#endif
312314
RETURN_IF_TRITONSERVER_ERROR(err);
313315
}

src/shared_library.cc

Lines changed: 122 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -60,47 +60,83 @@ SharedLibrary::~SharedLibrary()
6060
}
6161

6262
Status
63-
SharedLibrary::SetLibraryDirectory(const std::string& path)
63+
SharedLibrary::AddLibraryDirectory(
64+
const std::string& path, void** directory_cookie)
6465
{
6566
#ifdef _WIN32
66-
LOG_VERBOSE(1) << "SetLibraryDirectory: path = " << path;
67+
LOG_VERBOSE(1) << "AddLibraryDirectory: path = " << path;
6768
std::wstring wpath = LocalizedPath::GetWindowsValidPath(path);
68-
if (!SetDllDirectoryW(wpath.c_str())) {
69-
LPSTR err_buffer = nullptr;
70-
size_t size = FormatMessageA(
71-
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
72-
FORMAT_MESSAGE_IGNORE_INSERTS,
73-
NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
74-
(LPSTR)&err_buffer, 0, NULL);
75-
std::string errstr(err_buffer, size);
76-
LocalFree(err_buffer);
69+
if (mAdditionalDependencyDirs.empty()) {
70+
*directory_cookie = nullptr;
71+
if (!SetDllDirectoryW(wpath.c_str())) {
72+
LPSTR err_buffer = nullptr;
73+
size_t size = FormatMessageA(
74+
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
75+
FORMAT_MESSAGE_IGNORE_INSERTS,
76+
NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
77+
(LPSTR)&err_buffer, 0, NULL);
78+
std::string errstr(err_buffer, size);
79+
LocalFree(err_buffer);
7780

78-
return Status(
79-
Status::Code::NOT_FOUND,
80-
"unable to set dll path " + path + ": " + errstr);
81+
return Status(
82+
Status::Code::NOT_FOUND,
83+
"unable to set dll path " + path + ": " + errstr);
84+
}
85+
} else {
86+
*directory_cookie = AddDllDirectory(wpath.c_str());
87+
if (*directory_cookie == nullptr) {
88+
LPSTR err_buffer = nullptr;
89+
size_t size = FormatMessageA(
90+
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
91+
FORMAT_MESSAGE_IGNORE_INSERTS,
92+
NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
93+
(LPSTR)&err_buffer, 0, NULL);
94+
std::string errstr(err_buffer, size);
95+
LocalFree(err_buffer);
96+
97+
return Status(
98+
Status::Code::NOT_FOUND,
99+
"unable to add dll path " + path + ": " + errstr);
100+
}
81101
}
82102
#endif
83103

84104
return Status::Success;
85105
}
86106

87107
Status
88-
SharedLibrary::ResetLibraryDirectory()
108+
SharedLibrary::RemoveLibraryDirectory(void* directory_cookie)
89109
{
90110
#ifdef _WIN32
91-
LOG_VERBOSE(1) << "ResetLibraryDirectory";
92-
if (!SetDllDirectoryW(NULL)) {
93-
LPSTR err_buffer = nullptr;
94-
size_t size = FormatMessageA(
95-
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
96-
FORMAT_MESSAGE_IGNORE_INSERTS,
97-
NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
98-
(LPSTR)&err_buffer, 0, NULL);
99-
std::string errstr(err_buffer, size);
100-
LocalFree(err_buffer);
111+
LOG_VERBOSE(1) << "RemoveLibraryDirectory";
112+
if (mAdditionalDependencyDirs.empty()) {
113+
if (!SetDllDirectoryW(NULL)) {
114+
LPSTR err_buffer = nullptr;
115+
size_t size = FormatMessageA(
116+
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
117+
FORMAT_MESSAGE_IGNORE_INSERTS,
118+
NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
119+
(LPSTR)&err_buffer, 0, NULL);
120+
std::string errstr(err_buffer, size);
121+
LocalFree(err_buffer);
101122

102-
return Status(
103-
Status::Code::NOT_FOUND, "unable to reset dll path: " + errstr);
123+
return Status(
124+
Status::Code::NOT_FOUND, "unable to reset dll path: " + errstr);
125+
}
126+
} else {
127+
if (!RemoveDllDirectory(directory_cookie)) {
128+
LPSTR err_buffer = nullptr;
129+
size_t size = FormatMessageA(
130+
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
131+
FORMAT_MESSAGE_IGNORE_INSERTS,
132+
NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
133+
(LPSTR)&err_buffer, 0, NULL);
134+
std::string errstr(err_buffer, size);
135+
LocalFree(err_buffer);
136+
137+
return Status(
138+
Status::Code::NOT_FOUND, "unable to remove dll path: " + errstr);
139+
}
104140
}
105141
#endif
106142

@@ -126,17 +162,29 @@ SharedLibrary::OpenLibraryHandle(const std::string& path, void** handle)
126162
// Need to put shared library directory on the DLL path so that any
127163
// dependencies of the shared library are found
128164
const std::string library_dir = DirName(path);
129-
RETURN_IF_ERROR(SetLibraryDirectory(library_dir));
165+
void* directory_cookie = nullptr;
166+
RETURN_IF_ERROR(AddLibraryDirectory(library_dir, &directory_cookie));
130167

131168
// HMODULE is typedef of void*
132169
// https://docs.microsoft.com/en-us/windows/win32/winprog/windows-data-types
133170
LOG_VERBOSE(1) << "OpenLibraryHandle: path = " << path;
134171
std::wstring wpath = LocalizedPath::GetWindowsValidPath(path);
135-
*handle = LoadLibraryW(wpath.c_str());
172+
173+
174+
RETURN_IF_ERROR(AddAdditionalDependencyDirs());
175+
176+
uint32_t load_flags = 0x00000000;
177+
if (!mAdditionalDirHandles.empty()) {
178+
load_flags =
179+
LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_USER_DIRS;
180+
}
181+
*handle = LoadLibraryExW(wpath.c_str(), NULL, load_flags);
182+
183+
RETURN_IF_ERROR(RemoveAdditionalDependencyDirs());
136184

137185
// Remove the dll path added above... do this unconditionally before
138186
// check for failure in dll load.
139-
RETURN_IF_ERROR(ResetLibraryDirectory());
187+
RETURN_IF_ERROR(RemoveLibraryDirectory(directory_cookie));
140188

141189
if (*handle == nullptr) {
142190
LPSTR err_buffer = nullptr;
@@ -244,59 +292,26 @@ SharedLibrary::GetEntrypoint(
244292
return Status::Success;
245293
}
246294

295+
247296
Status
248-
SharedLibrary::AddAdditionalDependencyDir(
249-
const std::string& additional_path, std::wstring& original_path)
297+
SharedLibrary::SetAdditionalDependencyDirs(const std::string& additional_path)
250298
{
251299
#ifdef _WIN32
252-
const std::wstring PATH(L"Path");
253-
254300
if (additional_path.back() != ';') {
255301
return Status(
256302
Status::Code::INVALID_ARG,
257303
"backend config parameter \"additional-dependency-dirs\" is malformed. "
258304
"Each additional path provided should terminate with a ';'.");
259305
}
260306

261-
DWORD len = GetEnvironmentVariableW(PATH.c_str(), NULL, 0);
262-
if (len > 0) {
263-
original_path.resize(len);
264-
GetEnvironmentVariableW(PATH.c_str(), &original_path[0], len);
265-
} else {
266-
original_path = L"";
307+
size_t pos = 0, pos_end = 0;
308+
std::string token;
309+
while ((pos_end = additional_path.find(';', pos)) != std::string::npos) {
310+
token = additional_path.substr(pos, pos_end - pos);
311+
mAdditionalDependencyDirs.push_back(token);
312+
pos = pos_end + 1;
267313
}
268314

269-
LOG_VERBOSE(1) << "Environment before extending PATH: "
270-
<< std::string(original_path.begin(), original_path.end());
271-
272-
std::wstring updated_path_value =
273-
std::wstring(additional_path.begin(), additional_path.end());
274-
updated_path_value += original_path;
275-
276-
if (!SetEnvironmentVariableW(PATH.c_str(), updated_path_value.c_str())) {
277-
LPSTR err_buffer = nullptr;
278-
size_t size = FormatMessageA(
279-
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
280-
FORMAT_MESSAGE_IGNORE_INSERTS,
281-
NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
282-
(LPSTR)&err_buffer, 0, NULL);
283-
std::string errstr(err_buffer, size);
284-
LocalFree(err_buffer);
285-
return Status(
286-
Status::Code::INTERNAL,
287-
"failed to append user-provided directory to PATH " + errstr);
288-
}
289-
290-
if (LOG_VERBOSE_IS_ON(1)) {
291-
std::wstring path_after;
292-
len = GetEnvironmentVariableW(PATH.c_str(), NULL, 0);
293-
if (len > 0) {
294-
path_after.resize(len);
295-
GetEnvironmentVariableW(PATH.c_str(), &path_after[0], len);
296-
}
297-
LOG_VERBOSE(1) << "Environment after extending PATH: "
298-
<< std::string(path_after.begin(), path_after.end());
299-
}
300315
#else
301316
LOG_WARNING
302317
<< "The parameter \"additional-dependency-dirs\" has been specified but "
@@ -306,37 +321,49 @@ SharedLibrary::AddAdditionalDependencyDir(
306321
return Status::Success;
307322
}
308323

324+
#ifdef _WIN32
309325
Status
310-
SharedLibrary::RemoveAdditionalDependencyDir(const std::wstring& original_path)
326+
SharedLibrary::AddAdditionalDependencyDirs()
311327
{
312-
#ifdef _WIN32
313-
const std::wstring PATH(L"Path");
314-
if (!SetEnvironmentVariableW(PATH.c_str(), original_path.c_str())) {
315-
LPSTR err_buffer = nullptr;
316-
size_t size = FormatMessageA(
317-
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
318-
FORMAT_MESSAGE_IGNORE_INSERTS,
319-
NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
320-
(LPSTR)&err_buffer, 0, NULL);
321-
std::string errstr(err_buffer, size);
322-
LocalFree(err_buffer);
323-
return Status(
324-
Status::Code::INTERNAL,
325-
"failed to restore PATH to its original configuration " + errstr);
328+
LOG_VERBOSE(1) << "Adding " << mAdditionalDependencyDirs.size()
329+
<< " additional directories to search for dependencies";
330+
for (auto it = mAdditionalDependencyDirs.begin();
331+
it != mAdditionalDependencyDirs.end(); it++) {
332+
void* additional_dir_cookie = nullptr;
333+
RETURN_IF_ERROR(AddLibraryDirectory(*it, &additional_dir_cookie));
334+
mAdditionalDirHandles.push_back(additional_dir_cookie);
326335
}
327336

328-
if (LOG_VERBOSE_IS_ON(1)) {
329-
std::wstring path_after;
330-
DWORD len = GetEnvironmentVariableW(PATH.c_str(), NULL, 0);
331-
if (len > 0) {
332-
path_after.resize(len);
333-
GetEnvironmentVariableW(PATH.c_str(), &path_after[0], len);
337+
return Status::Success;
338+
}
339+
340+
Status
341+
SharedLibrary::RemoveAdditionalDependencyDirs()
342+
{
343+
for (auto it = mAdditionalDirHandles.begin();
344+
it != mAdditionalDirHandles.end(); it++) {
345+
if (*it == nullptr) {
346+
return Status(
347+
Status::Code::INTERNAL,
348+
"failed to remove a non-existent additional directory ");
349+
}
350+
351+
if (RemoveDllDirectory(*it)) {
352+
if (LOG_VERBOSE_IS_ON(1)) {
353+
LOG_VERBOSE(1) << "Removed an additional directory.";
354+
}
355+
} else {
356+
if (LOG_VERBOSE_IS_ON(1)) {
357+
LOG_VERBOSE(1) << "Failed to remove additional directory.";
358+
}
359+
return Status(
360+
Status::Code::INTERNAL, "unable to remove dependency directory");
334361
}
335-
LOG_VERBOSE(1) << "Environment after restoring PATH: "
336-
<< std::string(path_after.begin(), path_after.end());
337362
}
338-
#endif
363+
mAdditionalDirHandles.clear();
364+
339365
return Status::Success;
340366
}
367+
#endif
341368

342369
}} // namespace triton::core

0 commit comments

Comments
 (0)