Skip to content

Commit 71293ea

Browse files
authored
Defer deletion of reloadable remap plugins (#11813)
* Defer deletion of reloadable remap plugins * Fix tests, since plugins now remains * Put the startup cleanup into a try-catch * Make autest happier during shutdown
1 parent 88d17d8 commit 71293ea

File tree

8 files changed

+45
-37
lines changed

8 files changed

+45
-37
lines changed

cmake/layout.cmake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ set(CMAKE_INSTALL_LOCALSTATEDIR
4343
CACHE STRING "localstatedir"
4444
)
4545
set(CMAKE_INSTALL_RUNSTATEDIR
46-
"${CMAKE_INSTALL_LOCALSTATEDIR}/trafficserver"
46+
"${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LOCALSTATEDIR}/trafficserver"
4747
CACHE STRING "runstatedir"
4848
)
4949
set(CMAKE_INSTALL_DATAROOTDIR

include/proxy/http/remap/PluginDso.h

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -170,12 +170,8 @@ class PluginDso : public PluginThreadContext
170170
static constexpr const char *const _tag = "plugin_dso"; /** @brief log tag used by this class */
171171
static const DbgCtl &_dbg_ctl();
172172
swoc::file::file_time_type _mtime{fs::file_time_type::min()}; /* @brief modification time of the DSO's file, used for checking */
173-
bool _preventiveCleaning = true;
174-
175-
static Ptr<LoadedPlugins>
176-
_plugins; /** @brief a global list of plugins, usually maintained by a plugin factory or plugin instance itself */
177-
std::atomic<int> _instanceCount{
178-
0}; /** @brief used for properly calling "done" and "indicate config reload" methods by the factory */
173+
static Ptr<LoadedPlugins> _plugins; /** @brief a global list of plugins */
174+
std::atomic<int> _instanceCount{0}; /** @brief used for properly calling "done" and "indicate config reload" */
179175
};
180176

181177
inline const DbgCtl &

include/proxy/http/remap/PluginFactory.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,12 +99,13 @@ class PluginFactory
9999
RemapPluginInst *getRemapPlugin(const fs::path &configPath, int argc, char **argv, std::string &error, bool dynamicReloadEnabled);
100100

101101
virtual const char *getUuid();
102-
void clean(std::string &error);
103102

104103
void deactivate();
105104
void indicatePreReload();
106105
void indicatePostReload(bool reloadSuccessful);
107106

107+
static void cleanup(); // For startup, clean out all temporary directory we may have left from before
108+
108109
protected:
109110
PluginDso *findByEffectivePath(const fs::path &path, bool dynamicReloadEnabled);
110111
fs::path getEffectivePath(const fs::path &configPath);
@@ -117,7 +118,6 @@ class PluginFactory
117118

118119
ATSUuid *_uuid = nullptr;
119120
std::error_code _ec;
120-
bool _preventiveCleaning = true;
121121

122122
static constexpr const char *const _tag = "plugin_factory"; /** @brief log tag used by this class */
123123
static const DbgCtl &_dbg_ctl();

src/proxy/http/remap/PluginDso.cc

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ PluginDso::PluginDso(const fs::path &configPath, const fs::path &effectivePath,
6868
PluginDso::~PluginDso()
6969
{
7070
std::string error;
71+
7172
(void)unload(error);
7273
}
7374

@@ -136,11 +137,6 @@ PluginDso::load(std::string &error, const fs::path &compilerPath)
136137
PluginError("plugin '%s' failed to load: %s", _configPath.c_str(), error.c_str());
137138
}
138139
}
139-
140-
/* Remove the runtime DSO copy even if we succeed loading to avoid leftovers after crashes */
141-
if (_preventiveCleaning) {
142-
clean(error);
143-
}
144140
}
145141
PluginDbg(_dbg_ctl(), "plugin '%s' finished loading DSO", _configPath.c_str());
146142

src/proxy/http/remap/PluginFactory.cc

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include "../../../iocore/eventsystem/P_EventSystem.h"
3737

3838
#include <algorithm> /* std::swap */
39+
#include <filesystem>
3940

4041
RemapPluginInst::RemapPluginInst(RemapPluginInfo &plugin) : _plugin(plugin)
4142
{
@@ -102,7 +103,16 @@ PluginFactory::~PluginFactory()
102103
_instList.apply([](RemapPluginInst *pluginInst) -> void { delete pluginInst; });
103104
_instList.clear();
104105

105-
fs::remove_all(_runtimeDir, _ec);
106+
if (!TSSystemState::is_event_system_shut_down()) {
107+
uint32_t elevate_access = 0;
108+
109+
REC_ReadConfigInteger(elevate_access, "proxy.config.plugin.load_elevated");
110+
ElevateAccess access(elevate_access ? ElevateAccess::FILE_PRIVILEGE : 0);
111+
112+
fs::remove_all(_runtimeDir, _ec);
113+
} else {
114+
fs::remove_all(_runtimeDir, _ec); // Try anyways
115+
}
106116

107117
PluginDbg(_dbg_ctl(), "destroyed plugin factory %s", getUuid());
108118
delete _uuid;
@@ -226,9 +236,6 @@ PluginFactory::getRemapPlugin(const fs::path &configPath, int argc, char **argv,
226236
delete plugin;
227237
}
228238

229-
if (dynamicReloadEnabled && _preventiveCleaning) {
230-
clean(error);
231-
}
232239
} else {
233240
/* Plugin DSO load failed. */
234241
PluginDbg(_dbg_ctl(), "plugin '%s' DSO load failed", configPath.c_str());
@@ -276,6 +283,30 @@ PluginFactory::getEffectivePath(const fs::path &configPath)
276283
return path;
277284
}
278285

286+
void
287+
PluginFactory::cleanup()
288+
{
289+
std::error_code ec;
290+
std::string path(RecConfigReadRuntimeDir());
291+
292+
try {
293+
if (path.starts_with("/") && std::filesystem::is_directory(path)) {
294+
for (const auto &entry : std::filesystem::directory_iterator(path, ec)) {
295+
if (entry.is_directory()) {
296+
std::string dir_name = entry.path().string();
297+
int dash_count = std::count(dir_name.begin(), dir_name.end(), '-'); // All UUIDs have 4 dashes
298+
299+
if (dash_count == 4) {
300+
std::filesystem::remove_all(dir_name, ec);
301+
}
302+
}
303+
}
304+
}
305+
} catch (std::exception &e) {
306+
PluginError("Error cleaning up runtime directory: %s", e.what());
307+
}
308+
}
309+
279310
/**
280311
* @brief Find a plugin by path from our linked plugin list by using plugin effective (canonical) path
281312
*
@@ -326,9 +357,3 @@ PluginFactory::indicatePostReload(bool reloadSuccessful)
326357

327358
PluginDso::loadedPlugins()->indicatePostReload(reloadSuccessful, pluginUsed, getUuid());
328359
}
329-
330-
void
331-
PluginFactory::clean(std::string & /* error ATS_UNUSED */)
332-
{
333-
fs::remove_all(_runtimeDir, _ec);
334-
}

src/proxy/http/remap/unit-tests/test_PluginDso.cc

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,6 @@ class PluginDsoUnitTest : public PluginDso
6666
PluginDsoUnitTest(const fs::path &configPath, const fs::path &effectivePath, const fs::path &runtimePath)
6767
: PluginDso(configPath, effectivePath, runtimePath)
6868
{
69-
/* don't remove runtime DSO copy preventively so we can check if it was created properly */
70-
_preventiveCleaning = false;
7169
}
7270

7371
virtual void

src/proxy/http/remap/unit-tests/test_PluginFactory.cc

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,7 @@ static fs::path tempComponent = fs::path("c71e2bab-90dc-4770-9535-c9304c3de38e")
6868
class PluginFactoryUnitTest : public PluginFactory
6969
{
7070
public:
71-
PluginFactoryUnitTest(const fs::path &tempComponent)
72-
{
73-
_tempComponent = tempComponent;
74-
_preventiveCleaning = false;
75-
}
71+
PluginFactoryUnitTest(const fs::path &tempComponent) { _tempComponent = tempComponent; }
7672

7773
protected:
7874
const char *
@@ -305,9 +301,7 @@ SCENARIO("loading plugins", "[plugin][core]")
305301
validateSuccessfulConfigPathTest(plugin, error, effectivePath, runtimePath);
306302
CHECK(nullptr != PluginDso::loadedPlugins()->findByEffectivePath(effectivePath, isPluginDynamicReloadEnabled()));
307303

308-
// check Dso at effective path still exists while copy at runtime path doesn't
309304
CHECK(fs::exists(plugin->_plugin.effectivePath()));
310-
CHECK(!fs::exists(plugin->_plugin.runtimePath()));
311305
}
312306

313307
teardownConfigPathTest(factory);
@@ -606,13 +600,10 @@ checkTwoLoadedVersionsDifferent(const RemapPluginInst *plugin_v1, const RemapPlu
606600
// 2 versions can be different only when dynamic reload enabled
607601
CHECK(isPluginDynamicReloadEnabled());
608602

609-
// check Dso at effective path still exists while the copy at runtime path doesn't
610603
CHECK(plugin_v1->_plugin.effectivePath() != plugin_v1->_plugin.runtimePath());
611604
CHECK(fs::exists(plugin_v1->_plugin.effectivePath()));
612-
CHECK(!fs::exists(plugin_v1->_plugin.runtimePath()));
613605
CHECK(plugin_v2->_plugin.effectivePath() != plugin_v2->_plugin.runtimePath());
614606
CHECK(fs::exists(plugin_v2->_plugin.effectivePath()));
615-
CHECK(!fs::exists(plugin_v2->_plugin.runtimePath()));
616607
}
617608

618609
void

src/traffic_server/traffic_server.cc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1786,7 +1786,6 @@ configure_io_uring()
17861786
//
17871787
// Main
17881788
//
1789-
17901789
int
17911790
main(int /* argc ATS_UNUSED */, const char **argv)
17921791
{
@@ -1926,6 +1925,9 @@ main(int /* argc ATS_UNUSED */, const char **argv)
19261925
signal_register_crash_handler(crash_logger_invoke);
19271926
}
19281927

1928+
// Clean out any remnant temporary plugin (UUID named) directories.
1929+
PluginFactory::cleanup();
1930+
19291931
#if TS_USE_POSIX_CAP
19301932
// Change the user of the process.
19311933
// Do this before we start threads so we control the user id of the

0 commit comments

Comments
 (0)