From 257d635de870107d76b310310969a23f5a7510f4 Mon Sep 17 00:00:00 2001 From: sebaszm <45654185+sebaszm@users.noreply.github.com> Date: Tue, 24 Sep 2024 20:47:31 +0200 Subject: [PATCH] DSO search in-process/OOP unification (#1761) Co-authored-by: Pierre Wielders --- Source/Thunder/PluginServer.h | 80 +++++++++++++++------------ Source/ThunderPlugin/Process.cpp | 95 ++++++++++++++++++-------------- Source/com/Communicator.h | 24 ++++++-- Source/core/Library.cpp | 2 - Source/plugins/Shell.cpp | 4 +- 5 files changed, 119 insertions(+), 86 deletions(-) diff --git a/Source/Thunder/PluginServer.h b/Source/Thunder/PluginServer.h index 769fcb036..6d1b72ad5 100644 --- a/Source/Thunder/PluginServer.h +++ b/Source/Thunder/PluginServer.h @@ -1287,7 +1287,7 @@ namespace PluginHost { { ASSERT(_connection == nullptr); - void* result(_administrator.Instantiate(object, waitTime, sessionId, DataPath(), PersistentPath(), VolatilePath())); + void* result(_administrator.Instantiate(object, waitTime, sessionId, DataPath(), PersistentPath(), VolatilePath(), _administrator.Configuration().LinkerPluginPaths())); if (result != nullptr) { _connection = _administrator.RemoteConnection(sessionId); @@ -1373,43 +1373,38 @@ namespace PluginHost { RPC::IStringIterator* GetLibrarySearchPaths(const string& locator) const override { - std::vector all_paths; - const std::vector temp = _administrator.Configuration().LinkerPluginPaths(); - string rootPath(PluginHost::Service::Configuration().SystemRootPath.Value()); + std::vector searchPaths; - if (rootPath.empty() == false) { - rootPath = Core::Directory::Normalize(rootPath); - } + const string normalized(Core::File::Normalize(locator)); + const string rootPath(Core::Directory::Normalize(PluginHost::Service::Configuration().SystemRootPath)); - if (!temp.empty()) - { - // additionaly defined user paths - for (const string& s : temp) { - if (rootPath.empty() == true) { - all_paths.push_back(Core::Directory::Normalize(s) + locator); + ASSERT_VERBOSE((normalized.empty() == locator.empty()), "path normalization failed"); + ASSERT_VERBOSE((rootPath.empty() == PluginHost::Service::Configuration().SystemRootPath.Value().empty()), "path normalization failed"); + + if (normalized.empty() == false) { + if (Core::File::IsPathAbsolute(locator) == true) { + searchPaths.push_back(Core::File::Normalize(rootPath + normalized)); + } + else { + const std::vector& linkerPaths = _administrator.Configuration().LinkerPluginPaths(); + + if (linkerPaths.empty() == false) { + // override system paths + for (const string& path : linkerPaths) { + searchPaths.push_back(Core::Directory::Normalize(rootPath + path) + normalized); + } } else { - all_paths.push_back(rootPath + Core::Directory::Normalize(s) + locator); + // system configured paths + searchPaths.push_back(Core::Directory::Normalize(rootPath + DataPath()) + normalized); + searchPaths.push_back(Core::Directory::Normalize(rootPath + PersistentPath()) + normalized); + searchPaths.push_back(Core::Directory::Normalize(rootPath + SystemPath()) + normalized); + searchPaths.push_back(Core::Directory::Normalize(rootPath + PluginPath()) + normalized); } } } - else if (rootPath.empty() == false) - { - // system configured paths - all_paths.push_back(rootPath + DataPath() + locator); - all_paths.push_back(rootPath + PersistentPath() + locator); - all_paths.push_back(rootPath + SystemPath() + locator); - all_paths.push_back(rootPath + PluginPath() + locator); - } - else { - // system configured paths - all_paths.push_back(DataPath() + locator); - all_paths.push_back(PersistentPath() + locator); - all_paths.push_back(SystemPath() + locator); - all_paths.push_back(PluginPath() + locator); - } - return (Core::ServiceType::Create(all_paths)); + return (Core::ServiceType::Create(searchPaths)); } Core::Library LoadLibrary(const string& name) { @@ -1417,10 +1412,15 @@ namespace PluginHost { Core::Library result; RPC::IStringIterator* all_paths = GetLibrarySearchPaths(name); + ASSERT(all_paths != nullptr); + string element; while((all_paths->Next(element) == true) && (progressedState <= 2)) { + + TRACE_L1("attempting to load library %s", element.c_str()); + Core::File libraryToLoad(element); - + if (libraryToLoad.Exists() == true) { if (progressedState == 0) { progressedState = 1; @@ -2086,6 +2086,7 @@ namespace PluginHost { const string& proxyStubPath, const string& observableProxyStubPath, const string& postMortemPath, + const std::vector& linkerPaths, const uint8_t softKillCheckWaitTime, const uint8_t hardKillCheckWaitTime, const bool delegatedReleases, @@ -2103,6 +2104,7 @@ namespace PluginHost { #else , _application(EXPAND_AND_QUOTE(HOSTING_COMPROCESS)) #endif + , _linkerPaths(linkerPaths) , _adminLock() , _requestObservers() , _proxyStubObserver(*this, observableProxyStubPath) @@ -2141,9 +2143,9 @@ namespace PluginHost { } public: - void* Create(uint32_t& connectionId, const RPC::Object& instance, const uint32_t waitTime, const string& dataPath, const string& persistentPath, const string& volatilePath) + void* Create(uint32_t& connectionId, const RPC::Object& instance, const uint32_t waitTime, const string& dataPath, const string& persistentPath, const string& volatilePath, const std::vector& linkerPaths) { - return (RPC::Communicator::Create(connectionId, instance, RPC::Config(RPC::Communicator::Connector(), _application, persistentPath, _systemPath, dataPath, volatilePath, _appPath, RPC::Communicator::ProxyStubPath(), _postMortemPath), waitTime)); + return (RPC::Communicator::Create(connectionId, instance, RPC::Config(RPC::Communicator::Connector(), _application, persistentPath, _systemPath, dataPath, volatilePath, _appPath, RPC::Communicator::ProxyStubPath(), _postMortemPath, linkerPaths), waitTime)); } const string& PersistentPath() const { @@ -2177,6 +2179,10 @@ namespace PluginHost { { return (_application); } + const std::vector& LinkerPaths() const + { + return (_linkerPaths); + } void Register(RPC::IRemoteConnection::INotification* sink) { RPC::Communicator::Register(sink); @@ -2328,6 +2334,7 @@ namespace PluginHost { const string _observableProxyStubPath; const string _postMortemPath; const string _application; + std::vector _linkerPaths; mutable Core::CriticalSection _adminLock; Observers _requestObservers; ProxyStubObserver _proxyStubObserver; @@ -2405,7 +2412,7 @@ namespace PluginHost { } uint32_t id; - RPC::Config config(_connector, _comms.Application(), persistentPath, _comms.SystemPath(), dataPath, volatilePath, _comms.AppPath(), _comms.ProxyStubPath(), _comms.PostMortemPath()); + RPC::Config config(_connector, _comms.Application(), persistentPath, _comms.SystemPath(), dataPath, volatilePath, _comms.AppPath(), _comms.ProxyStubPath(), _comms.PostMortemPath(), _comms.LinkerPaths()); RPC::Object instance(libraryName, className, callsign, interfaceId, version, user, group, threads, priority, RPC::Object::HostType::LOCAL, systemRootPath, _T(""), configuration); RPC::Communicator::Process process(requestId, config, instance); @@ -2652,6 +2659,7 @@ namespace PluginHost { server._config.ProxyStubPath(), server._config.ObservableProxyStubPath(), server._config.PostMortemPath(), + server._config.LinkerPluginPaths(), server._config.SoftKillCheckWaitTime(), server._config.HardKillCheckWaitTime(), server._config.DelegatedReleases(), @@ -2895,9 +2903,9 @@ namespace PluginHost { return (result); } - void* Instantiate(const RPC::Object& object, const uint32_t waitTime, uint32_t& sessionId, const string& dataPath, const string& persistentPath, const string& volatilePath) + void* Instantiate(const RPC::Object& object, const uint32_t waitTime, uint32_t& sessionId, const string& dataPath, const string& persistentPath, const string& volatilePath, const std::vector& linkerPaths) { - return (_processAdministrator.Create(sessionId, object, waitTime, dataPath, persistentPath, volatilePath)); + return (_processAdministrator.Create(sessionId, object, waitTime, dataPath, persistentPath, volatilePath, linkerPaths)); } void Destroy(const uint32_t id) { _processAdministrator.Destroy(id); diff --git a/Source/ThunderPlugin/Process.cpp b/Source/ThunderPlugin/Process.cpp index e8510e0ef..df3d64432 100644 --- a/Source/ThunderPlugin/Process.cpp +++ b/Source/ThunderPlugin/Process.cpp @@ -81,7 +81,6 @@ POP_WARNING() TRACE_L1("We still have living object [%d].", instances); } else { - TRACE_L1("All living objects are killed. Time for HaraKiri!!."); // Seems there is no more live here, time to signal the @@ -130,7 +129,6 @@ POP_WARNING() } void Run() { - Core::WorkerPool::Run(); Core::WorkerPool::Join(); } @@ -161,7 +159,7 @@ POP_WARNING() class ConsoleOptions : public Core::Options { public: ConsoleOptions(int argumentCount, TCHAR* arguments[]) - : Core::Options(argumentCount, arguments, _T("h:l:c:C:r:p:s:d:a:m:i:u:g:t:e:x:V:v:P:S:")) + : Core::Options(argumentCount, arguments, _T("h:l:c:C:r:p:s:d:a:m:i:u:g:t:e:x:V:v:P:S:f:")) , Locator(nullptr) , ClassName(nullptr) , Callsign(nullptr) @@ -180,6 +178,7 @@ POP_WARNING() , User(nullptr) , Group(nullptr) , Threads(1) + , LinkerPaths() { Parse(); } @@ -206,6 +205,7 @@ POP_WARNING() const TCHAR* User; const TCHAR* Group; uint8_t Threads; + std::vector LinkerPaths; private: string Strip(const TCHAR text[]) const @@ -236,28 +236,28 @@ POP_WARNING() RemoteChannel = argument; break; case 'p': - PersistentPath = Strip(argument); + PersistentPath = Core::Directory::Normalize(Strip(argument)); break; case 's': - SystemPath = Strip(argument); + SystemPath = Core::Directory::Normalize(Strip(argument)); break; case 'd': - DataPath = Strip(argument); + DataPath = Core::Directory::Normalize(Strip(argument)); break; case 'P': - PostMortemPath = Strip(argument); + PostMortemPath = Core::Directory::Normalize(Strip(argument)); break; case 'S': - SystemRootPath = Strip(argument); + SystemRootPath = Core::Directory::Normalize(Strip(argument)); break; case 'v': - VolatilePath = Strip(argument); + VolatilePath = Core::Directory::Normalize(Strip(argument)); break; case 'a': - AppPath = Strip(argument); + AppPath = Core::Directory::Normalize(Strip(argument)); break; case 'm': - ProxyStubPath = Strip(argument); + ProxyStubPath = Core::Directory::Normalize(Strip(argument)); break; case 'u': User = argument; @@ -277,6 +277,9 @@ POP_WARNING() case 't': Threads = Core::NumberType(Core::TextFragment(argument)).Value(); break; + case 'f': + LinkerPaths.push_back(Strip(argument)); + break; case 'h': default: RequestUsage(true); @@ -285,52 +288,59 @@ POP_WARNING() } }; - static void* CheckInstance(const string& path, const TCHAR locator[], const TCHAR className[], const uint32_t ID, const uint32_t version) + static void* CheckInstance(const string& path, const ConsoleOptions& options) { void* result = nullptr; if (path.empty() == false) { - Core::ServiceAdministrator& admin(Core::ServiceAdministrator::Instance()); - string libraryPath = locator; - if (libraryPath.empty() || (libraryPath[0] != '/')) { - // Relative path, prefix with path name. - string pathName(Core::Directory::Normalize(path)); - libraryPath = pathName + locator; - } + TRACE_L1("Attempting to load '%s' from %s...", options.ClassName, path.c_str()); - Core::Library library(libraryPath.c_str()); + Core::Library library(path.c_str()); if (library.IsLoaded() == true) { // Instantiate the object - result = admin.Instantiate(library, className, version, ID); + result = Core::ServiceAdministrator::Instance().Instantiate(library, options.ClassName, options.Version, options.InterfaceId); } } return (result); } - static void* AcquireInterfaces(ConsoleOptions& options) + static void* AcquireInterfaces(const ConsoleOptions& options) { void* result = nullptr; if ((options.Locator != nullptr) && (options.ClassName != nullptr)) { - string path = (!options.SystemRootPath.empty() ? options.SystemRootPath : "") + options.PersistentPath; - result = CheckInstance(path, options.Locator, options.ClassName, options.InterfaceId, options.Version); - if (result == nullptr) { - path = (!options.SystemRootPath.empty() ? options.SystemRootPath : "") + options.SystemPath; - result = CheckInstance(path, options.Locator, options.ClassName, options.InterfaceId, options.Version); + const string rootPath = Core::Directory::Normalize(options.SystemRootPath); + + if (Core::File::IsPathAbsolute(options.Locator) == true) { + result = CheckInstance(Core::File::Normalize(rootPath + options.Locator), options); + } + else if (options.LinkerPaths.empty() == false) { + // Linker paths override system paths + for (const string& linkerPath : options.LinkerPaths) { + result = CheckInstance((Core::Directory::Normalize(options.SystemRootPath + linkerPath) + options.Locator), options); + + if (result != nullptr) { + break; + } + } + } + else { + // System paths + result = CheckInstance((Core::Directory::Normalize(options.SystemRootPath + options.PersistentPath) + options.Locator), options); if (result == nullptr) { - path = (!options.SystemRootPath.empty() ? options.SystemRootPath : "") + options.DataPath; - result = CheckInstance(path, options.Locator, options.ClassName, options.InterfaceId, options.Version); + result = CheckInstance((Core::Directory::Normalize(options.SystemRootPath + options.SystemPath) + options.Locator), options); if (result == nullptr) { - string searchPath(options.AppPath.empty() == false ? Core::Directory::Normalize(options.AppPath) : string()); + result = CheckInstance((Core::Directory::Normalize(options.SystemRootPath + options.DataPath) + options.Locator), options); - path = (!options.SystemRootPath.empty() ? options.SystemRootPath : "") + searchPath; - result = CheckInstance((path + _T("Plugins/")), options.Locator, options.ClassName, options.InterfaceId, options.Version); + if (result == nullptr) { + result = CheckInstance((Core::Directory::Normalize(options.SystemRootPath + options.AppPath + _T("Plugins")) + options.Locator), options); + } } } } @@ -577,23 +587,26 @@ int main(int argc, char** argv) printf(" [-s ]\n"); printf(" [-d ]\n"); printf(" [-v ]\n"); + printf(" [-f ...\n"); printf(" [-a ]\n"); printf(" [-m ]\n"); printf(" [-P ]\n\n"); printf(" [-S ]\n\n"); + printf("\n"); printf("This application spawns a seperate process space for a plugin. The plugins"); printf("are searched in the same order as they are done in process. Starting from:\n"); - printf(" 1) /\n"); - printf(" 2) /\n"); - printf(" 3) /\n"); - printf(" 4) /Plugins/\n\n"); + printf(" 1) [system_path/]/\n"); + printf(" 2) [system_path/]/\n"); + printf(" 3) [system_path/]/\n"); + printf(" 4) [system_path/]/Plugins/\n\n"); + printf("\n"); + printf("Alternatively, if linker paths are specified:\n"); + printf(" 1) [system_path/]/locator\n"); + printf(" 2) [system_path/]/locator, ...\n"); + printf("\n"); printf("Within the DSO, the system looks for an object with , this object must implement "); printf("the interface, indicated byt the Id , and if passed, the object should be of "); printf("version . All these conditions must met for an object to be instantiated and thus run.\n\n"); - - for (uint8_t teller = 0; teller < argc; teller++) { - printf("Argument [%02d]: %s\n", teller, argv[teller]); - } } else { string callsign; if (options.Callsign != nullptr) { @@ -640,7 +653,7 @@ int main(int argc, char** argv) if (remoteNode.IsValid()) { void* base = nullptr; - TRACE_L1("Spawning a new plugin %s.", options.ClassName); + TRACE_L1("Spawning a new plugin %s", options.Callsign); // Firts make sure we apply the correct rights to our selves.. if (options.Group != nullptr) { diff --git a/Source/com/Communicator.h b/Source/com/Communicator.h index 35aea1ced..054a8644b 100644 --- a/Source/com/Communicator.h +++ b/Source/com/Communicator.h @@ -150,7 +150,6 @@ namespace RPC { return (*this); } - Object& operator=(Object&& move) noexcept { if (this != &move) { @@ -172,9 +171,9 @@ namespace RPC { move._version = ~0; move._threads = 0; move._priority = 0; - } - return (*this); - } + } + return (*this); + } public: inline const string& Locator() const @@ -262,6 +261,7 @@ namespace RPC { , _application() , _proxyStub() , _postMortem() + , _linker() { } Config( @@ -273,7 +273,8 @@ namespace RPC { const string& volatilePath, const string& applicationPath, const string& proxyStubPath, - const string& postMortem) + const string& postMortem, + const std::vector& linker) : _connector(connector) , _hostApplication(hostApplication) , _persistent(persistentPath) @@ -283,6 +284,7 @@ namespace RPC { , _application(applicationPath) , _proxyStub(proxyStubPath) , _postMortem(postMortem) + , _linker(linker) { } Config(const Config& copy) @@ -295,6 +297,7 @@ namespace RPC { , _application(copy._application) , _proxyStub(copy._proxyStub) , _postMortem(copy._postMortem) + , _linker(copy._linker) { } Config(Config&& move) noexcept @@ -307,6 +310,7 @@ namespace RPC { , _application(std::move(move._application)) , _proxyStub(std::move(move._proxyStub)) , _postMortem(std::move(move._postMortem)) + , _linker(std::move(move._linker)) { } ~Config() @@ -350,6 +354,10 @@ namespace RPC { { return (_postMortem); } + inline const std::vector& LinkerPaths() const + { + return (_linker); + } private: string _connector; @@ -361,6 +369,7 @@ namespace RPC { string _application; string _proxyStub; string _postMortem; + std::vector _linker; }; struct EXTERNAL IMonitorableProcess : public virtual Core::IUnknown { @@ -490,6 +499,9 @@ namespace RPC { if (config.VolatilePath().empty() == false) { _options.Add(_T("-v")).Add('"' + config.VolatilePath() + '"'); } + for (auto const& path : config.LinkerPaths()) { + _options.Add(_T("-f")).Add('"' + path + '"'); + } if (config.ProxyStubPath().empty() == false) { _options.Add(_T("-m")).Add('"' + config.ProxyStubPath() + '"'); } @@ -865,7 +877,7 @@ namespace RPC { TRACE_L1("Invalid process container configuration"); } else { - std::vector searchPaths(3); + std::vector searchPaths; #ifdef __DEBUG__ if (config.ContainerPath.IsSet() == true) { diff --git a/Source/core/Library.cpp b/Source/core/Library.cpp index 04575b3c7..4541ba3e0 100644 --- a/Source/core/Library.cpp +++ b/Source/core/Library.cpp @@ -114,8 +114,6 @@ namespace Core { _refCountedHandle->_name = GlobalSymbols; TRACE_L1("Loaded library with global symbols of the program"); } - - TRACE_L1("Loaded library: %s", fileName); } else { #ifdef __LINUX__ _error = dlerror(); diff --git a/Source/plugins/Shell.cpp b/Source/plugins/Shell.cpp index edcd0c8b5..9d3c8024f 100644 --- a/Source/plugins/Shell.cpp +++ b/Source/plugins/Shell.cpp @@ -42,8 +42,10 @@ namespace PluginHost result = Core::ServiceAdministrator::Instance().Instantiate(Core::Library(), className.c_str(), version, interface); } else { RPC::IStringIterator* all_paths = GetLibrarySearchPaths(locator); + ASSERT(all_paths != nullptr); + string element; - while (all_paths->Next(element) == true) { + while ((all_paths->Next(element) == true) && (result == nullptr)) { Core::File file(element.c_str()); if (file.Exists()) {