This is an automated email from the ASF dual-hosted git repository. zwoop pushed a commit to branch 9.0.x in repository https://gitbox.apache.org/repos/asf/trafficserver.git
The following commit(s) were added to refs/heads/9.0.x by this push: new f6c888c Premature DSO unload with "suicidal" continuations f6c888c is described below commit f6c888c4d8c18469a572341345527d6affe56b28 Author: Gancho Tenev <gan...@apache.org> AuthorDate: Mon Oct 21 19:27:39 2019 -0700 Premature DSO unload with "suicidal" continuations Fixed a problem with premature plugin DSO unloading when the following conditions are met: - if a continuation created from inside a plugin outlives the last configuration object that used it and becomes the last object relying on the plugin DSO - if the continuation event handler logic decides to destroy its own continuation with `TSContDestroy()` then the plugin DSO would get unloaded immediately before the event handler function reaches its end. (cherry picked from commit c269a5a8d2bed870f6cf27555a6673041beea655) --- proxy/http/remap/Makefile.am | 26 ++++-- proxy/http/remap/PluginDso.cc | 96 ++++++++++++++++++---- proxy/http/remap/PluginDso.h | 29 ++++++- proxy/http/remap/PluginFactory.cc | 47 ++++------- proxy/http/remap/PluginFactory.h | 3 +- proxy/http/remap/RemapConfig.cc | 1 + proxy/http/remap/RemapPluginInfo.cc | 20 +++-- .../http/remap/unit-tests/plugin_testing_common.h | 5 +- proxy/http/remap/unit-tests/test_PluginFactory.cc | 24 ++++++ 9 files changed, 183 insertions(+), 68 deletions(-) diff --git a/proxy/http/remap/Makefile.am b/proxy/http/remap/Makefile.am index 8973d1b..8275166 100644 --- a/proxy/http/remap/Makefile.am +++ b/proxy/http/remap/Makefile.am @@ -54,6 +54,16 @@ libhttp_remap_a_SOURCES = \ UrlRewrite.cc \ UrlRewrite.h +COMMON_PLUGINDSO_LDADDS = \ + $(OPENSSL_LIBS) \ + $(top_builddir)/iocore/eventsystem/libinkevent.a \ + $(top_builddir)/lib/records/librecords_p.a \ + $(top_builddir)/iocore/eventsystem/libinkevent.a \ + $(top_builddir)/src/tscore/libtscore.la \ + $(top_builddir)/mgmt/libmgmt_p.la \ + $(top_builddir)/proxy/shared/libUglyLogStubs.a \ + @HWLOC_LIBS@ + clang-tidy-local: $(libhttp_remap_a_SOURCES) $(CXX_Clang_Tidy) @@ -61,18 +71,20 @@ TESTS = $(check_PROGRAMS) check_PROGRAMS = test_PluginDso test_PluginFactory test_RemapPluginInfo test_PluginDso_CPPFLAGS = $(AM_CPPFLAGS) -I$(abs_top_srcdir)/tests/include -DPLUGIN_DSO_TESTS +test_PluginDso_LIBTOOLFLAGS = --preserve-dup-deps EXTRA_test_PluginDso_DEPENDENCIES = unit-tests/plugin_v1.la -test_PluginDso_LDADD = $(OPENSSL_LIBS) -test_PluginDso_LDFLAGS = $(AM_LDFLAGS) -L$(top_builddir)/src/tscore/.libs -ltscore +test_PluginDso_LDADD = $(COMMON_PLUGINDSO_LDADDS) +test_PluginDso_LDFLAGS = $(AM_LDFLAGS) test_PluginDso_SOURCES = \ unit-tests/test_PluginDso.cc \ unit-tests/plugin_testing_common.cc \ PluginDso.cc test_PluginFactory_CPPFLAGS = $(AM_CPPFLAGS) -I$(abs_top_srcdir)/tests/include -DPLUGIN_DSO_TESTS +test_PluginFactory_LIBTOOLFLAGS = --preserve-dup-deps EXTRA_test_PluginFactory_DEPENDENCIES = unit-tests/plugin_v1.la -test_PluginFactory_LDADD = $(OPENSSL_LIBS) -test_PluginFactory_LDFLAGS = $(AM_LDFLAGS) -L$(top_builddir)/src/tscore/.libs -ltscore +test_PluginFactory_LDADD = $(COMMON_PLUGINDSO_LDADDS) +test_PluginFactory_LDFLAGS = $(AM_LDFLAGS) test_PluginFactory_SOURCES = \ unit-tests/test_PluginFactory.cc \ unit-tests/plugin_testing_common.cc \ @@ -81,6 +93,7 @@ test_PluginFactory_SOURCES = \ RemapPluginInfo.cc test_RemapPluginInfo_CPPFLAGS = $(AM_CPPFLAGS) -I$(abs_top_srcdir)/tests/include -DPLUGIN_DSO_TESTS +test_RemapPluginInfo_LIBTOOLFLAGS = --preserve-dup-deps EXTRA_test_RemapPluginInfo_DEPENDENCIES = \ unit-tests/plugin_missing_init.la \ unit-tests/plugin_missing_doremap.la \ @@ -88,9 +101,8 @@ EXTRA_test_RemapPluginInfo_DEPENDENCIES = \ unit-tests/plugin_required_cb.la \ unit-tests/plugin_missing_newinstance.la \ unit-tests/plugin_testing_calls.la -test_RemapPluginInfo_LDADD = \ - $(OPENSSL_LIBS) -test_RemapPluginInfo_LDFLAGS = $(AM_LDFLAGS) -L$(top_builddir)/src/tscore/.libs -ltscore +test_RemapPluginInfo_LDADD = $(COMMON_PLUGINDSO_LDADDS) +test_RemapPluginInfo_LDFLAGS = $(AM_LDFLAGS) test_RemapPluginInfo_SOURCES = \ unit-tests/plugin_testing_common.cc \ unit-tests/plugin_testing_calls.cc \ diff --git a/proxy/http/remap/PluginDso.cc b/proxy/http/remap/PluginDso.cc index 24490fc..7bd4dcf 100644 --- a/proxy/http/remap/PluginDso.cc +++ b/proxy/http/remap/PluginDso.cc @@ -28,10 +28,14 @@ */ #include "PluginDso.h" +#include "P_Freer.h" +#include "P_EventSystem.h" #ifdef PLUGIN_DSO_TESTS #include "unit-tests/plugin_testing_common.h" #else #include "tscore/Diags.h" +#define PluginDebug Debug +#define PluginError Error #endif PluginDso::PluginDso(const fs::path &configPath, const fs::path &effectivePath, const fs::path &runtimePath) @@ -58,14 +62,14 @@ PluginDso::load(std::string &error) return false; } - Debug(_tag, "plugin '%s' started loading DSO", _configPath.c_str()); + PluginDebug(_tag, "plugin '%s' started loading DSO", _configPath.c_str()); /* Find plugin DSO looking through the search dirs */ if (_effectivePath.empty()) { error.append("empty effective path"); result = false; } else { - Debug(_tag, "plugin '%s' effective path: %s", _configPath.c_str(), _effectivePath.c_str()); + PluginDebug(_tag, "plugin '%s' effective path: %s", _configPath.c_str(), _effectivePath.c_str()); /* Copy the installed plugin DSO to a runtime directory */ std::error_code ec; @@ -75,13 +79,13 @@ PluginDso::load(std::string &error) error.assign(temp_error); result = false; } else { - Debug(_tag, "plugin '%s' runtime path: %s", _configPath.c_str(), _runtimePath.c_str()); + PluginDebug(_tag, "plugin '%s' runtime path: %s", _configPath.c_str(), _runtimePath.c_str()); /* Save the time for later checking if DSO got modified in consecutive DSO reloads */ std::error_code ec; fs::file_status fs = fs::status(_effectivePath, ec); _mtime = fs::modification_time(fs); - Debug(_tag, "plugin '%s' mоdification time %ld", _configPath.c_str(), _mtime); + PluginDebug(_tag, "plugin '%s' mоdification time %ld", _configPath.c_str(), _mtime); /* Now attemt to load the plugin DSO */ if ((_dlh = dlopen(_runtimePath.c_str(), RTLD_NOW)) == nullptr) { @@ -96,7 +100,7 @@ PluginDso::load(std::string &error) clean(error); result = false; - Error("plugin '%s' failed to load: %s", _configPath.c_str(), error.c_str()); + PluginError("plugin '%s' failed to load: %s", _configPath.c_str(), error.c_str()); } } @@ -105,7 +109,7 @@ PluginDso::load(std::string &error) clean(error); } } - Debug(_tag, "plugin '%s' finished loading DSO", _configPath.c_str()); + PluginDebug(_tag, "plugin '%s' finished loading DSO", _configPath.c_str()); return result; } @@ -229,17 +233,16 @@ void PluginDso::acquire() { this->refcount_inc(); - Debug(_tag, "plugin DSO acquire (ref-count:%d, dso-addr:%p)", this->refcount(), this); + PluginDebug(_tag, "plugin DSO acquire (ref-count:%d, dso-addr:%p)", this->refcount(), this); } void PluginDso::release() { - Debug(_tag, "plugin DSO release (ref-count:%d, dso-addr:%p)", this->refcount() - 1, this); + PluginDebug(_tag, "plugin DSO release (ref-count:%d, dso-addr:%p)", this->refcount() - 1, this); if (0 == this->refcount_dec()) { - Debug(_tag, "unloading plugin DSO '%s' (dso-addr:%p)", _configPath.c_str(), this); - _list.erase(this); - delete this; + PluginDebug(_tag, "unloading plugin DSO '%s' (dso-addr:%p)", _configPath.c_str(), this); + _plugins->remove(this); } } @@ -247,14 +250,14 @@ void PluginDso::incInstanceCount() { _instanceCount.refcount_inc(); - Debug(_tag, "instance count (inst-count:%d, dso-addr:%p)", _instanceCount.refcount(), this); + PluginDebug(_tag, "instance count (inst-count:%d, dso-addr:%p)", _instanceCount.refcount(), this); } void PluginDso::decInstanceCount() { _instanceCount.refcount_dec(); - Debug(_tag, "instance count (inst-count:%d, dso-addr:%p)", _instanceCount.refcount(), this); + PluginDebug(_tag, "instance count (inst-count:%d, dso-addr:%p)", _instanceCount.refcount(), this); } int @@ -263,4 +266,69 @@ PluginDso::instanceCount() return _instanceCount.refcount(); } -PluginDso::PluginList PluginDso::_list; +void +PluginDso::LoadedPlugins::add(PluginDso *plugin) +{ + SCOPED_MUTEX_LOCK(lock, _mutex, this_ethread()); + + _list.append(plugin); +} + +void +PluginDso::LoadedPlugins::remove(PluginDso *plugin) +{ + SCOPED_MUTEX_LOCK(lock, _mutex, this_ethread()); + + _list.erase(plugin); + this_ethread()->schedule_imm(new DeleterContinuation<PluginDso>(plugin)); +} + +PluginDso * +PluginDso::LoadedPlugins::findByEffectivePath(const fs::path &path) +{ + struct stat sb; + time_t mtime = 0; + if (0 == stat(path.c_str(), &sb)) { + mtime = sb.st_mtime; + } + + SCOPED_MUTEX_LOCK(lock, _mutex, this_ethread()); + + auto spot = std::find_if(_list.begin(), _list.end(), [&](PluginDso const &plugin) -> bool { + return (0 == path.string().compare(plugin.effectivePath().string()) && (mtime == plugin.modTime())); + }); + return spot == _list.end() ? nullptr : static_cast<PluginDso *>(spot); +} + +void +PluginDso::LoadedPlugins::indicatePreReload(const char *factoryId) +{ + SCOPED_MUTEX_LOCK(lock, _mutex, this_ethread()); + + PluginDebug(_tag, "indicated config is going to be reloaded by factory '%s' to %zu plugin%s", factoryId, _list.count(), + _list.count() != 1 ? "s" : ""); + + _list.apply([](PluginDso &plugin) -> void { plugin.indicatePreReload(); }); +} + +void +PluginDso::LoadedPlugins::indicatePostReload(bool reloadSuccessful, const std::unordered_map<PluginDso *, int> &pluginUsed, + const char *factoryId) +{ + SCOPED_MUTEX_LOCK(lock, _mutex, this_ethread()); + + PluginDebug(_tag, "indicated config is done reloading by factory '%s' to %zu plugin%s", factoryId, _list.count(), + _list.count() != 1 ? "s" : ""); + + for (auto &plugin : _list) { + TSRemapReloadStatus status = TSREMAP_CONFIG_RELOAD_FAILURE; + if (reloadSuccessful) { + /* reload succeeded but was the plugin instantiated by this factory? */ + status = (pluginUsed.end() == pluginUsed.find(&plugin) ? TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_UNUSED : + TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_USED); + } + plugin.indicatePostReload(status); + } +} + +Ptr<PluginDso::LoadedPlugins> PluginDso::_plugins; diff --git a/proxy/http/remap/PluginDso.h b/proxy/http/remap/PluginDso.h index e542718..47fc080 100644 --- a/proxy/http/remap/PluginDso.h +++ b/proxy/http/remap/PluginDso.h @@ -29,6 +29,7 @@ #pragma once +#include <unordered_map> #include <dlfcn.h> #include <vector> #include <ctime> @@ -39,6 +40,7 @@ namespace fs = ts::file; #include "tscore/Ptr.h" +#include "I_EventSystem.h" #include "tscpp/util/IntrusiveDList.h" class PluginThreadContext : public RefCountObj @@ -88,6 +90,30 @@ public: void decInstanceCount(); int instanceCount(); + class LoadedPlugins : public RefCountObj + { + public: + LoadedPlugins() : _mutex(new_ProxyMutex()) {} + void add(PluginDso *plugin); + void remove(PluginDso *plugin); + PluginDso *findByEffectivePath(const fs::path &path); + void indicatePreReload(const char *factoryId); + void indicatePostReload(bool reloadSuccessful, const std::unordered_map<PluginDso *, int> &pluginUsed, const char *factoryId); + + private: + PluginList _list; /** @brief plugin list */ + Ptr<ProxyMutex> _mutex; /** @brief mutex used when updating the plugin list from multiple threads */ + }; + + static const Ptr<LoadedPlugins> & + loadedPlugins() + { + if (!_plugins) { + _plugins = new LoadedPlugins(); + } + return _plugins; + } + protected: void clean(std::string &error); @@ -102,6 +128,7 @@ protected: time_t _mtime = 0; /* @brief modification time of the DSO's file, used for checking */ bool _preventiveCleaning = true; - static PluginList _list; /** @brief a global list of plugins, usually maintained by a plugin factory or plugin instance itself */ + static Ptr<LoadedPlugins> + _plugins; /** @brief a global list of plugins, usually maintained by a plugin factory or plugin instance itself */ RefCountObj _instanceCount; /** @brief used for properly calling "done" and "indicate config reload" methods by the factory */ }; diff --git a/proxy/http/remap/PluginFactory.cc b/proxy/http/remap/PluginFactory.cc index 9491228..8fc55af 100644 --- a/proxy/http/remap/PluginFactory.cc +++ b/proxy/http/remap/PluginFactory.cc @@ -30,7 +30,10 @@ #include "unit-tests/plugin_testing_common.h" #else #include "tscore/Diags.h" +#define PluginDebug Debug +#define PluginError Error #endif +#include "P_EventSystem.h" #include <algorithm> /* std::swap */ @@ -91,7 +94,7 @@ PluginFactory::PluginFactory() } } - Debug(_tag, "created plugin factory %s", getUuid()); + PluginDebug(_tag, "created plugin factory %s", getUuid()); } PluginFactory::~PluginFactory() @@ -101,7 +104,7 @@ PluginFactory::~PluginFactory() fs::remove(_runtimeDir, _ec); - Debug(_tag, "destroyed plugin factory %s", getUuid()); + PluginDebug(_tag, "destroyed plugin factory %s", getUuid()); delete _uuid; } @@ -109,7 +112,7 @@ PluginFactory & PluginFactory::addSearchDir(const fs::path &searchDir) { _searchDirs.push_back(searchDir); - Debug(_tag, "added plugin search dir %s", searchDir.c_str()); + PluginDebug(_tag, "added plugin search dir %s", searchDir.c_str()); return *this; } @@ -117,7 +120,7 @@ PluginFactory & PluginFactory::setRuntimeDir(const fs::path &runtimeDir) { _runtimeDir = runtimeDir / fs::path(getUuid()); - Debug(_tag, "set plugin runtime dir %s", runtimeDir.c_str()); + PluginDebug(_tag, "set plugin runtime dir %s", runtimeDir.c_str()); return *this; } @@ -153,7 +156,7 @@ PluginFactory::getRemapPlugin(const fs::path &configPath, int argc, char **argv, if (nullptr == plugin) { /* The plugin requested have not been loaded yet. */ - Debug(_tag, "plugin '%s' has not been loaded yet, loading as remap plugin", configPath.c_str()); + PluginDebug(_tag, "plugin '%s' has not been loaded yet, loading as remap plugin", configPath.c_str()); fs::path runtimePath; runtimePath /= _runtimeDir; @@ -168,7 +171,7 @@ PluginFactory::getRemapPlugin(const fs::path &configPath, int argc, char **argv, plugin = new RemapPluginInfo(configPath, effectivePath, runtimePath); if (nullptr != plugin) { if (plugin->load(error)) { - _list.append(plugin); + PluginDso::loadedPlugins()->add(plugin); if (plugin->init(error)) { inst = RemapPluginInst::init(plugin, argc, argv, error); @@ -185,7 +188,7 @@ PluginFactory::getRemapPlugin(const fs::path &configPath, int argc, char **argv, } } } else { - Debug(_tag, "plugin '%s' has already been loaded", configPath.c_str()); + PluginDebug(_tag, "plugin '%s' has already been loaded", configPath.c_str()); inst = RemapPluginInst::init(plugin, argc, argv, error); if (nullptr != inst) { _instList.append(inst); @@ -234,15 +237,7 @@ PluginFactory::getEffectivePath(const fs::path &configPath) PluginDso * PluginFactory::findByEffectivePath(const fs::path &path) { - struct stat sb; - time_t mtime = 0; - if (0 == stat(path.c_str(), &sb)) { - mtime = sb.st_mtime; - } - auto spot = std::find_if(_list.begin(), _list.end(), [&](PluginDso const &plugin) -> bool { - return (0 == path.string().compare(plugin.effectivePath().string()) && (mtime == plugin.modTime())); - }); - return spot == _list.end() ? nullptr : static_cast<PluginDso *>(spot); + return PluginDso::loadedPlugins()->findByEffectivePath(path); } /** @@ -255,7 +250,7 @@ PluginFactory::findByEffectivePath(const fs::path &path) void PluginFactory::deactivate() { - Debug(_tag, "deactivate configuration used by factory '%s'", getUuid()); + PluginDebug(_tag, "deactivate configuration used by factory '%s'", getUuid()); _instList.apply([](RemapPluginInst &pluginInst) -> void { pluginInst.done(); }); } @@ -266,10 +261,7 @@ PluginFactory::deactivate() void PluginFactory::indicatePreReload() { - Debug(_tag, "indicated config is going to be reloaded by factory '%s' to %zu plugin%s", getUuid(), _list.count(), - _list.count() != 1 ? "s" : ""); - - _list.apply([](PluginDso &plugin) -> void { plugin.indicatePreReload(); }); + PluginDso::loadedPlugins()->indicatePreReload(getUuid()); } /** @@ -278,24 +270,13 @@ PluginFactory::indicatePreReload() void PluginFactory::indicatePostReload(bool reloadSuccessful) { - Debug(_tag, "indicated config is done reloading by factory '%s' to %zu plugin%s", getUuid(), _list.count(), - _list.count() != 1 ? "s" : ""); - /* Find out which plugins (DSO) are actually instantiated by this factory */ std::unordered_map<PluginDso *, int> pluginUsed; for (auto &inst : _instList) { pluginUsed[&(inst._plugin)]++; } - for (auto &plugin : _list) { - TSRemapReloadStatus status = TSREMAP_CONFIG_RELOAD_FAILURE; - if (reloadSuccessful) { - /* reload succeeded but was the plugin instantiated by this factory? */ - status = (pluginUsed.end() == pluginUsed.find(&plugin) ? TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_UNUSED : - TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_USED); - } - plugin.indicatePostReload(status); - } + PluginDso::loadedPlugins()->indicatePostReload(reloadSuccessful, pluginUsed, getUuid()); } void diff --git a/proxy/http/remap/PluginFactory.h b/proxy/http/remap/PluginFactory.h index 5982db4..3c2902c 100644 --- a/proxy/http/remap/PluginFactory.h +++ b/proxy/http/remap/PluginFactory.h @@ -85,8 +85,7 @@ public: */ class PluginFactory { - using PluginInstList = ts::IntrusiveDList<RemapPluginInst::Linkage>; - PluginDso::PluginList &_list = PluginDso::_list; + using PluginInstList = ts::IntrusiveDList<RemapPluginInst::Linkage>; public: PluginFactory(); diff --git a/proxy/http/remap/RemapConfig.cc b/proxy/http/remap/RemapConfig.cc index 424f4bf..63bca48 100644 --- a/proxy/http/remap/RemapConfig.cc +++ b/proxy/http/remap/RemapConfig.cc @@ -815,6 +815,7 @@ remap_load_plugin(const char **argv, int argc, url_mapping *mp, char *errbuf, in bool result = true; if (nullptr == pi) { snprintf(errbuf, errbufsize, "%s", error.c_str()); + result = false; } else { mp->add_plugin_instance(pi); } diff --git a/proxy/http/remap/RemapPluginInfo.cc b/proxy/http/remap/RemapPluginInfo.cc index 8f8962b..736fd4d 100644 --- a/proxy/http/remap/RemapPluginInfo.cc +++ b/proxy/http/remap/RemapPluginInfo.cc @@ -34,6 +34,8 @@ #include "unit-tests/plugin_testing_common.h" #else #include "tscore/Diags.h" +#define PluginDebug Debug +#define PluginError Error #endif /** @@ -53,7 +55,7 @@ RemapPluginInfo::getFunctionSymbol(const char *symbol) std::string error; /* ignore the error, return nullptr if symbol not defined */ void *address = nullptr; if (getSymbol(symbol, address, error)) { - Debug(_tag, "plugin '%s' found symbol '%s'", _configPath.c_str(), symbol); + PluginDebug(_tag, "plugin '%s' found symbol '%s'", _configPath.c_str(), symbol); } return reinterpret_cast<T *>(address); } @@ -109,9 +111,9 @@ RemapPluginInfo::load(std::string &error) } if (valid) { - Debug(_tag, "plugin '%s' callbacks validated", _configPath.c_str()); + PluginDebug(_tag, "plugin '%s' callbacks validated", _configPath.c_str()); } else { - Error("plugin '%s' callbacks validation failed: %s", _configPath.c_str(), error.c_str()); + PluginError("plugin '%s' callbacks validation failed: %s", _configPath.c_str(), error.c_str()); } return valid; } @@ -123,7 +125,7 @@ RemapPluginInfo::init(std::string &error) TSRemapInterface ri; bool result = true; - Debug(_tag, "started initializing plugin '%s'", _configPath.c_str()); + PluginDebug(_tag, "started initializing plugin '%s'", _configPath.c_str()); /* A buffer to get the error from the plugin instance init function, be defensive here. */ char tmpbuf[2048]; @@ -145,7 +147,7 @@ RemapPluginInfo::init(std::string &error) resetPluginContext(); - Debug(_tag, "finished initializing plugin '%s'", _configPath.c_str()); + PluginDebug(_tag, "finished initializing plugin '%s'", _configPath.c_str()); return result; } @@ -165,7 +167,7 @@ RemapPluginInfo::initInstance(int argc, char **argv, void **ih, std::string &err TSReturnCode res = TS_SUCCESS; bool result = true; - Debug(_tag, "started initializing instance of plugin '%s'", _configPath.c_str()); + PluginDebug(_tag, "started initializing instance of plugin '%s'", _configPath.c_str()); /* A buffer to get the error from the plugin instance init function, be defensive here. */ char tmpbuf[2048]; @@ -198,7 +200,7 @@ RemapPluginInfo::initInstance(int argc, char **argv, void **ih, std::string &err } } - Debug(_tag, "finished initializing instance of plugin '%s'", _configPath.c_str()); + PluginDebug(_tag, "finished initializing instance of plugin '%s'", _configPath.c_str()); return result; } @@ -274,12 +276,12 @@ RemapPluginInfo::setPluginContext() { _tempContext = pluginThreadContext; pluginThreadContext = this; - Debug(_tag, "change plugin context from dso-addr:%p to dso-addr:%p", pluginThreadContext, _tempContext); + PluginDebug(_tag, "change plugin context from dso-addr:%p to dso-addr:%p", pluginThreadContext, _tempContext); } inline void RemapPluginInfo::resetPluginContext() { - Debug(_tag, "change plugin context from dso-addr:%p to dso-addr:%p (restore)", this, pluginThreadContext); + PluginDebug(_tag, "change plugin context from dso-addr:%p to dso-addr:%p (restore)", this, pluginThreadContext); pluginThreadContext = _tempContext; } diff --git a/proxy/http/remap/unit-tests/plugin_testing_common.h b/proxy/http/remap/unit-tests/plugin_testing_common.h index f96c420..fd01dd0 100644 --- a/proxy/http/remap/unit-tests/plugin_testing_common.h +++ b/proxy/http/remap/unit-tests/plugin_testing_common.h @@ -93,8 +93,9 @@ extern "C" { typedef void *GetPluginDebugObjectFunction(void); GetPluginDebugObjectFunction getPluginDebugObjectTest; -#define Debug(category, fmt, ...) PrintToStdErr("(%s) %s:%d:%s() " fmt "\n", category, __FILE__, __LINE__, __func__, ##__VA_ARGS__) -#define Error(fmt, ...) PrintToStdErr("%s:%d:%s() " fmt "\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__) +#define PluginDebug(category, fmt, ...) \ + PrintToStdErr("(%s) %s:%d:%s() " fmt "\n", category, __FILE__, __LINE__, __func__, ##__VA_ARGS__) +#define PluginError(fmt, ...) PrintToStdErr("%s:%d:%s() " fmt "\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__) void PrintToStdErr(const char *fmt, ...); #ifdef __cplusplus diff --git a/proxy/http/remap/unit-tests/test_PluginFactory.cc b/proxy/http/remap/unit-tests/test_PluginFactory.cc index 1456f20..d42f058 100644 --- a/proxy/http/remap/unit-tests/test_PluginFactory.cc +++ b/proxy/http/remap/unit-tests/test_PluginFactory.cc @@ -35,6 +35,30 @@ #include "plugin_testing_common.h" #include "../PluginFactory.h" #include "../PluginDso.h" +#include "I_EventSystem.h" +#include "tscore/I_Layout.h" +#include "diags.i" + +#define TEST_THREADS 2 +struct EventProcessorListener : Catch::TestEventListenerBase { + using TestEventListenerBase::TestEventListenerBase; + + void + testRunStarting(Catch::TestRunInfo const &testRunInfo) override + { + Layout::create(); + init_diags("", nullptr); + RecProcessInit(RECM_STAND_ALONE); + + ink_event_system_init(EVENT_SYSTEM_MODULE_PUBLIC_VERSION); + eventProcessor.start(TEST_THREADS, 1048576); + + EThread *main_thread = new EThread; + main_thread->set_specific(); + } +}; + +CATCH_REGISTER_LISTENER(EventProcessorListener); thread_local PluginThreadContext *pluginThreadContext;