This is an automated email from the ASF dual-hosted git repository.
zwoop pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
The following commit(s) were added to refs/heads/master by this push:
new 71293ea3dd Defer deletion of reloadable remap plugins (#11813)
71293ea3dd is described below
commit 71293ea3dd5fd6431918f7ea6025ecdcb628c46e
Author: Leif Hedstrom <[email protected]>
AuthorDate: Tue Oct 15 13:56:44 2024 -0600
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
---
cmake/layout.cmake | 2 +-
include/proxy/http/remap/PluginDso.h | 8 +---
include/proxy/http/remap/PluginFactory.h | 4 +-
src/proxy/http/remap/PluginDso.cc | 6 +--
src/proxy/http/remap/PluginFactory.cc | 45 +++++++++++++++++-----
src/proxy/http/remap/unit-tests/test_PluginDso.cc | 2 -
.../http/remap/unit-tests/test_PluginFactory.cc | 11 +-----
src/traffic_server/traffic_server.cc | 4 +-
8 files changed, 45 insertions(+), 37 deletions(-)
diff --git a/cmake/layout.cmake b/cmake/layout.cmake
index 69a7b23970..72dcbf0fd7 100644
--- a/cmake/layout.cmake
+++ b/cmake/layout.cmake
@@ -43,7 +43,7 @@ set(CMAKE_INSTALL_LOCALSTATEDIR
CACHE STRING "localstatedir"
)
set(CMAKE_INSTALL_RUNSTATEDIR
- "${CMAKE_INSTALL_LOCALSTATEDIR}/trafficserver"
+ "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LOCALSTATEDIR}/trafficserver"
CACHE STRING "runstatedir"
)
set(CMAKE_INSTALL_DATAROOTDIR
diff --git a/include/proxy/http/remap/PluginDso.h
b/include/proxy/http/remap/PluginDso.h
index e7c84e97c9..d3ea8087a2 100644
--- a/include/proxy/http/remap/PluginDso.h
+++ b/include/proxy/http/remap/PluginDso.h
@@ -170,12 +170,8 @@ protected:
static constexpr const char *const _tag = "plugin_dso"; /** @brief log tag
used by this class */
static const DbgCtl &_dbg_ctl();
swoc::file::file_time_type _mtime{fs::file_time_type::min()}; /* @brief
modification time of the DSO's file, used for checking */
- bool _preventiveCleaning = true;
-
- static Ptr<LoadedPlugins>
- _plugins; /** @brief a global list of plugins, usually maintained by a
plugin factory or plugin instance itself */
- std::atomic<int> _instanceCount{
- 0}; /** @brief used for properly calling "done" and "indicate config
reload" methods by the factory */
+ static Ptr<LoadedPlugins> _plugins; /** @brief a
global list of plugins */
+ std::atomic<int> _instanceCount{0}; /** @brief used for properly
calling "done" and "indicate config reload" */
};
inline const DbgCtl &
diff --git a/include/proxy/http/remap/PluginFactory.h
b/include/proxy/http/remap/PluginFactory.h
index 9007c80c9c..fd08c00000 100644
--- a/include/proxy/http/remap/PluginFactory.h
+++ b/include/proxy/http/remap/PluginFactory.h
@@ -99,12 +99,13 @@ public:
RemapPluginInst *getRemapPlugin(const fs::path &configPath, int argc, char
**argv, std::string &error, bool dynamicReloadEnabled);
virtual const char *getUuid();
- void clean(std::string &error);
void deactivate();
void indicatePreReload();
void indicatePostReload(bool reloadSuccessful);
+ static void cleanup(); // For startup, clean out all temporary directory we
may have left from before
+
protected:
PluginDso *findByEffectivePath(const fs::path &path, bool
dynamicReloadEnabled);
fs::path getEffectivePath(const fs::path &configPath);
@@ -117,7 +118,6 @@ protected:
ATSUuid *_uuid = nullptr;
std::error_code _ec;
- bool _preventiveCleaning = true;
static constexpr const char *const _tag = "plugin_factory"; /** @brief log
tag used by this class */
static const DbgCtl &_dbg_ctl();
diff --git a/src/proxy/http/remap/PluginDso.cc
b/src/proxy/http/remap/PluginDso.cc
index 6c23823687..cd0499d8e6 100644
--- a/src/proxy/http/remap/PluginDso.cc
+++ b/src/proxy/http/remap/PluginDso.cc
@@ -68,6 +68,7 @@ PluginDso::PluginDso(const fs::path &configPath, const
fs::path &effectivePath,
PluginDso::~PluginDso()
{
std::string error;
+
(void)unload(error);
}
@@ -136,11 +137,6 @@ PluginDso::load(std::string &error, const fs::path
&compilerPath)
PluginError("plugin '%s' failed to load: %s", _configPath.c_str(),
error.c_str());
}
}
-
- /* Remove the runtime DSO copy even if we succeed loading to avoid
leftovers after crashes */
- if (_preventiveCleaning) {
- clean(error);
- }
}
PluginDbg(_dbg_ctl(), "plugin '%s' finished loading DSO",
_configPath.c_str());
diff --git a/src/proxy/http/remap/PluginFactory.cc
b/src/proxy/http/remap/PluginFactory.cc
index 3f13543a71..c5217cee1a 100644
--- a/src/proxy/http/remap/PluginFactory.cc
+++ b/src/proxy/http/remap/PluginFactory.cc
@@ -36,6 +36,7 @@
#include "../../../iocore/eventsystem/P_EventSystem.h"
#include <algorithm> /* std::swap */
+#include <filesystem>
RemapPluginInst::RemapPluginInst(RemapPluginInfo &plugin) : _plugin(plugin)
{
@@ -102,7 +103,16 @@ PluginFactory::~PluginFactory()
_instList.apply([](RemapPluginInst *pluginInst) -> void { delete pluginInst;
});
_instList.clear();
- fs::remove_all(_runtimeDir, _ec);
+ if (!TSSystemState::is_event_system_shut_down()) {
+ uint32_t elevate_access = 0;
+
+ REC_ReadConfigInteger(elevate_access, "proxy.config.plugin.load_elevated");
+ ElevateAccess access(elevate_access ? ElevateAccess::FILE_PRIVILEGE : 0);
+
+ fs::remove_all(_runtimeDir, _ec);
+ } else {
+ fs::remove_all(_runtimeDir, _ec); // Try anyways
+ }
PluginDbg(_dbg_ctl(), "destroyed plugin factory %s", getUuid());
delete _uuid;
@@ -226,9 +236,6 @@ PluginFactory::getRemapPlugin(const fs::path &configPath,
int argc, char **argv,
delete plugin;
}
- if (dynamicReloadEnabled && _preventiveCleaning) {
- clean(error);
- }
} else {
/* Plugin DSO load failed. */
PluginDbg(_dbg_ctl(), "plugin '%s' DSO load failed",
configPath.c_str());
@@ -276,6 +283,30 @@ PluginFactory::getEffectivePath(const fs::path &configPath)
return path;
}
+void
+PluginFactory::cleanup()
+{
+ std::error_code ec;
+ std::string path(RecConfigReadRuntimeDir());
+
+ try {
+ if (path.starts_with("/") && std::filesystem::is_directory(path)) {
+ for (const auto &entry : std::filesystem::directory_iterator(path, ec)) {
+ if (entry.is_directory()) {
+ std::string dir_name = entry.path().string();
+ int dash_count = std::count(dir_name.begin(),
dir_name.end(), '-'); // All UUIDs have 4 dashes
+
+ if (dash_count == 4) {
+ std::filesystem::remove_all(dir_name, ec);
+ }
+ }
+ }
+ }
+ } catch (std::exception &e) {
+ PluginError("Error cleaning up runtime directory: %s", e.what());
+ }
+}
+
/**
* @brief Find a plugin by path from our linked plugin list by using plugin
effective (canonical) path
*
@@ -326,9 +357,3 @@ PluginFactory::indicatePostReload(bool reloadSuccessful)
PluginDso::loadedPlugins()->indicatePostReload(reloadSuccessful, pluginUsed,
getUuid());
}
-
-void
-PluginFactory::clean(std::string & /* error ATS_UNUSED */)
-{
- fs::remove_all(_runtimeDir, _ec);
-}
diff --git a/src/proxy/http/remap/unit-tests/test_PluginDso.cc
b/src/proxy/http/remap/unit-tests/test_PluginDso.cc
index 72eb31f33e..e3d4071494 100644
--- a/src/proxy/http/remap/unit-tests/test_PluginDso.cc
+++ b/src/proxy/http/remap/unit-tests/test_PluginDso.cc
@@ -66,8 +66,6 @@ public:
PluginDsoUnitTest(const fs::path &configPath, const fs::path &effectivePath,
const fs::path &runtimePath)
: PluginDso(configPath, effectivePath, runtimePath)
{
- /* don't remove runtime DSO copy preventively so we can check if it was
created properly */
- _preventiveCleaning = false;
}
virtual void
diff --git a/src/proxy/http/remap/unit-tests/test_PluginFactory.cc
b/src/proxy/http/remap/unit-tests/test_PluginFactory.cc
index 9053d9668f..6997da4d34 100644
--- a/src/proxy/http/remap/unit-tests/test_PluginFactory.cc
+++ b/src/proxy/http/remap/unit-tests/test_PluginFactory.cc
@@ -68,11 +68,7 @@ static fs::path tempComponent =
fs::path("c71e2bab-90dc-4770-9535-c9304c3de38e")
class PluginFactoryUnitTest : public PluginFactory
{
public:
- PluginFactoryUnitTest(const fs::path &tempComponent)
- {
- _tempComponent = tempComponent;
- _preventiveCleaning = false;
- }
+ PluginFactoryUnitTest(const fs::path &tempComponent) { _tempComponent =
tempComponent; }
protected:
const char *
@@ -305,9 +301,7 @@ SCENARIO("loading plugins", "[plugin][core]")
validateSuccessfulConfigPathTest(plugin, error, effectivePath,
runtimePath);
CHECK(nullptr !=
PluginDso::loadedPlugins()->findByEffectivePath(effectivePath,
isPluginDynamicReloadEnabled()));
- // check Dso at effective path still exists while copy at runtime path
doesn't
CHECK(fs::exists(plugin->_plugin.effectivePath()));
- CHECK(!fs::exists(plugin->_plugin.runtimePath()));
}
teardownConfigPathTest(factory);
@@ -606,13 +600,10 @@ checkTwoLoadedVersionsDifferent(const RemapPluginInst
*plugin_v1, const RemapPlu
// 2 versions can be different only when dynamic reload enabled
CHECK(isPluginDynamicReloadEnabled());
- // check Dso at effective path still exists while the copy at runtime path
doesn't
CHECK(plugin_v1->_plugin.effectivePath() !=
plugin_v1->_plugin.runtimePath());
CHECK(fs::exists(plugin_v1->_plugin.effectivePath()));
- CHECK(!fs::exists(plugin_v1->_plugin.runtimePath()));
CHECK(plugin_v2->_plugin.effectivePath() !=
plugin_v2->_plugin.runtimePath());
CHECK(fs::exists(plugin_v2->_plugin.effectivePath()));
- CHECK(!fs::exists(plugin_v2->_plugin.runtimePath()));
}
void
diff --git a/src/traffic_server/traffic_server.cc
b/src/traffic_server/traffic_server.cc
index 0a7d8e0634..f00e365cc1 100644
--- a/src/traffic_server/traffic_server.cc
+++ b/src/traffic_server/traffic_server.cc
@@ -1786,7 +1786,6 @@ configure_io_uring()
//
// Main
//
-
int
main(int /* argc ATS_UNUSED */, const char **argv)
{
@@ -1926,6 +1925,9 @@ main(int /* argc ATS_UNUSED */, const char **argv)
signal_register_crash_handler(crash_logger_invoke);
}
+ // Clean out any remnant temporary plugin (UUID named) directories.
+ PluginFactory::cleanup();
+
#if TS_USE_POSIX_CAP
// Change the user of the process.
// Do this before we start threads so we control the user id of the