Skip to content

Commit 1955a84

Browse files
authored
Add support for custom python environments (triton-inference-server#55)
* Add support for custom python environments * Remove boost * Add support for using custom Python backend stub * Fix custom python backend stub support * Do not ignore return value of chdir and cwd * Review edits + improve the error message when there is not enough shared memory * Review edits
1 parent 1debbd8 commit 1955a84

File tree

8 files changed

+609
-206
lines changed

8 files changed

+609
-206
lines changed

CMakeLists.txt

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,20 +80,21 @@ FetchContent_Declare(
8080
)
8181
FetchContent_MakeAvailable(pybind11)
8282

83-
include_directories(${CMAKE_CURRENT_BINARY_DIR})
84-
85-
find_package(Python3 COMPONENTS Interpreter Development REQUIRED)
83+
find_package(ZLIB REQUIRED)
8684
find_package(Threads REQUIRED)
8785

86+
include_directories(${CMAKE_CURRENT_BINARY_DIR})
8887
configure_file(src/libtriton_python.ldscript libtriton_python.ldscript COPYONLY)
8988

9089
add_library(
9190
triton-python-backend SHARED
91+
src/python.cc
9292
src/pb_utils.cc
9393
src/pb_utils.h
94+
src/pb_env.cc
95+
src/pb_env.h
9496
src/shm_manager.cc
9597
src/shm_manager.h
96-
src/python.cc
9798
)
9899

99100
add_executable(
@@ -104,7 +105,6 @@ add_executable(
104105
src/shm_manager.cc
105106
src/shm_manager.h
106107
)
107-
108108
set_property(TARGET triton-python-backend-stub PROPERTY OUTPUT_NAME triton_python_backend_stub)
109109

110110
add_library(
@@ -136,15 +136,17 @@ target_link_libraries(
136136
PRIVATE
137137
triton-core-serverstub # from repo-core
138138
triton-backend-utils # from repo-backend
139+
ZLIB::ZLIB
140+
-larchive # shared memory
139141
)
140142

141143
target_link_libraries(
142144
triton-python-backend-stub
143145
PRIVATE
144-
Python3::Python
145146
Threads::Threads
146147
pybind11::embed
147148
triton-backend-utils # from repo-backend
149+
-larchive # libarchive
148150
-lrt # shared memory
149151
)
150152

src/pb_env.cc

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
// Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
2+
//
3+
// Redistribution and use in source and binary forms, with or without
4+
// modification, are permitted provided that the following conditions
5+
// are met:
6+
// * Redistributions of source code must retain the above copyright
7+
// notice, this list of conditions and the following disclaimer.
8+
// * Redistributions in binary form must reproduce the above copyright
9+
// notice, this list of conditions and the following disclaimer in the
10+
// documentation and/or other materials provided with the distribution.
11+
// * Neither the name of NVIDIA CORPORATION nor the names of its
12+
// contributors may be used to endorse or promote products derived
13+
// from this software without specific prior written permission.
14+
//
15+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
16+
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17+
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18+
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
19+
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20+
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21+
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22+
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23+
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24+
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25+
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26+
27+
#include "pb_env.h"
28+
29+
#include <archive.h>
30+
#include <archive_entry.h>
31+
#include <fts.h>
32+
#include <boost/filesystem.hpp>
33+
#include <boost/iostreams/copy.hpp>
34+
#include <boost/iostreams/filter/gzip.hpp>
35+
#include <boost/iostreams/filtering_streambuf.hpp>
36+
#include <cstdlib>
37+
#include <cstring>
38+
#include <iostream>
39+
#include "pb_utils.h"
40+
41+
42+
namespace triton { namespace backend { namespace python {
43+
44+
void
45+
RecursiveDirectoryDelete(const char* dir)
46+
{
47+
FTS* ftsp = NULL;
48+
FTSENT* curr;
49+
50+
char* files[] = {(char*)dir, NULL};
51+
52+
ftsp = fts_open(files, FTS_NOCHDIR | FTS_PHYSICAL | FTS_XDEV, NULL);
53+
if (!ftsp) {
54+
}
55+
56+
while ((curr = fts_read(ftsp))) {
57+
switch (curr->fts_info) {
58+
case FTS_NS:
59+
case FTS_DNR:
60+
case FTS_ERR:
61+
throw PythonBackendException(
62+
std::string("fts_read error: ") + curr->fts_accpath +
63+
" error: " + strerror(curr->fts_errno));
64+
break;
65+
66+
case FTS_DC:
67+
case FTS_DOT:
68+
case FTS_NSOK:
69+
break;
70+
71+
case FTS_D:
72+
// Do nothing. Directories are deleted in FTS_DP
73+
break;
74+
75+
case FTS_DP:
76+
case FTS_F:
77+
case FTS_SL:
78+
case FTS_SLNONE:
79+
case FTS_DEFAULT:
80+
if (remove(curr->fts_accpath) < 0) {
81+
throw PythonBackendException(
82+
std::string("Failed to remove ") + curr->fts_path +
83+
" error: " + strerror(curr->fts_errno));
84+
}
85+
break;
86+
}
87+
}
88+
}
89+
90+
EnvironmentManager::EnvironmentManager()
91+
{
92+
char tmp_dir_template[PATH_MAX + 1];
93+
strcpy(tmp_dir_template, "/tmp/python_env_XXXXXX");
94+
95+
char* env_path = mkdtemp(tmp_dir_template);
96+
if (env_path == nullptr) {
97+
throw PythonBackendException(
98+
"Failed to create temporary directory for Python environments.");
99+
}
100+
strcpy(base_path_, tmp_dir_template);
101+
}
102+
103+
std::string
104+
EnvironmentManager::ExtractIfNotExtracted(std::string env_path)
105+
{
106+
// Lock the mutex. Only a single thread should modify the map.
107+
std::lock_guard<std::mutex> lk(mutex_);
108+
char canonical_env_path[PATH_MAX + 1];
109+
110+
char* err = realpath(env_path.c_str(), canonical_env_path);
111+
if (err == nullptr) {
112+
throw PythonBackendException(
113+
std::string("Failed to get the canonical path for ") + env_path + ".");
114+
}
115+
116+
// Extract only if the env has not been extracted yet.
117+
if (env_map_.find(canonical_env_path) == env_map_.end()) {
118+
std::string dst_env_path(
119+
std::string(base_path_) + "/" + std::to_string(env_map_.size()));
120+
121+
std::string canonical_env_path_str(canonical_env_path);
122+
123+
int status =
124+
mkdir(dst_env_path.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
125+
if (status == 0) {
126+
ExtractTarFile(canonical_env_path_str, dst_env_path);
127+
} else {
128+
throw PythonBackendException(
129+
std::string("Failed to create environment directory for '") +
130+
dst_env_path.c_str() + "'.");
131+
}
132+
133+
// Add the path to the list of environments
134+
env_map_.insert({canonical_env_path, dst_env_path});
135+
return dst_env_path;
136+
} else {
137+
return env_map_.find(canonical_env_path)->second;
138+
}
139+
}
140+
141+
EnvironmentManager::~EnvironmentManager()
142+
{
143+
RecursiveDirectoryDelete(base_path_);
144+
}
145+
146+
}}} // namespace triton::backend::python

src/pb_env.h

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
2+
//
3+
// Redistribution and use in source and binary forms, with or without
4+
// modification, are permitted provided that the following conditions
5+
// are met:
6+
// * Redistributions of source code must retain the above copyright
7+
// notice, this list of conditions and the following disclaimer.
8+
// * Redistributions in binary form must reproduce the above copyright
9+
// notice, this list of conditions and the following disclaimer in the
10+
// documentation and/or other materials provided with the distribution.
11+
// * Neither the name of NVIDIA CORPORATION nor the names of its
12+
// contributors may be used to endorse or promote products derived
13+
// from this software without specific prior written permission.
14+
//
15+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
16+
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17+
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18+
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
19+
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20+
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21+
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22+
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23+
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24+
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25+
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26+
27+
#pragma once
28+
#include <climits>
29+
#include <map>
30+
#include <mutex>
31+
#include <string>
32+
33+
namespace triton { namespace backend { namespace python {
34+
35+
//
36+
// A class that manages Python environments
37+
//
38+
class EnvironmentManager {
39+
std::map<std::string, std::string> env_map_;
40+
char base_path_[PATH_MAX + 1];
41+
std::mutex mutex_;
42+
43+
public:
44+
EnvironmentManager();
45+
46+
// Extracts the tar.gz file in the 'env_path' if it has not been
47+
// already extracted.
48+
std::string ExtractIfNotExtracted(std::string env_path);
49+
~EnvironmentManager();
50+
};
51+
52+
}}} // namespace triton::backend::python

0 commit comments

Comments
 (0)