From 81d9fa9bc737c09132390cb7ebfe44adb43f0d93 Mon Sep 17 00:00:00 2001 From: Anthony Geay Date: Fri, 23 Feb 2024 18:39:25 +0100 Subject: [PATCH] [EDF29576] : Move to python implementation of driver and integrate monitoring into driver. --- idl/SALOME_Component.idl | 5 +- idl/SALOME_ContainerManager.idl | 5 +- src/Basics/PythonCppUtils.hxx | 11 +++- src/Container/Container_i.cxx | 51 ++++++++++++++----- src/Container/SALOME_Container.py | 4 ++ src/Container/SALOME_ContainerManager.cxx | 31 +++++++++-- src/Container/SALOME_ContainerManager.hxx | 7 +++ .../SALOME_Container_SignalsHandler.cxx | 1 + src/Container/SALOME_Container_i.hxx | 5 +- src/KERNEL_PY/__init__.py | 22 +++++--- src/NamingService/NamingService.i | 9 ++++ 11 files changed, 124 insertions(+), 27 deletions(-) diff --git a/idl/SALOME_Component.idl b/idl/SALOME_Component.idl index a2a402d5f..b3585af45 100644 --- a/idl/SALOME_Component.idl +++ b/idl/SALOME_Component.idl @@ -190,9 +190,12 @@ module Engines void setVerbosity(in boolean activated, in string level); - //! Shutdown the Container process. + //! Shutdown the Container process. Shutdown is not immediate. It waits for all remaining invokation completion. void Shutdown(); + //! Shutdown the Container process. Shutdown is immediate for this method. + void ShutdownNow(); + //! Returns the hostname of the container string getHostName(); diff --git a/idl/SALOME_ContainerManager.idl b/idl/SALOME_ContainerManager.idl index be92c24c0..d06c3c06b 100644 --- a/idl/SALOME_ContainerManager.idl +++ b/idl/SALOME_ContainerManager.idl @@ -86,8 +86,11 @@ interface ContainerManager //! Currently: get, start, getorstart, findorstart, find Container GiveContainer(in ContainerParameters params) raises (SALOME::SALOME_Exception); - //! Shutdown all containers that have been launched by the container manager + //! Shutdown all containers that have been launched by the container manager. This termination is soft. It means that orb.shutdown is invoked meaning that completion of all CORBA void ShutdownContainers(); + + //! Stronger version than ShutdownContainers. This method does not wait for completion of last CORBA invokation on containers. It terminates them + void ShutdownContainersNow(); long GetTimeOutToLaunchServerInSecond(); diff --git a/src/Basics/PythonCppUtils.hxx b/src/Basics/PythonCppUtils.hxx index 905005566..8a54b86bb 100644 --- a/src/Basics/PythonCppUtils.hxx +++ b/src/Basics/PythonCppUtils.hxx @@ -34,7 +34,7 @@ class AutoPyRef { public: AutoPyRef(PyObject *pyobj=nullptr):_pyobj(pyobj) { } - virtual ~AutoPyRef() { release(); } + ~AutoPyRef() { release(); } AutoPyRef(const AutoPyRef& other):_pyobj(other._pyobj) { if(_pyobj) Py_XINCREF(_pyobj); } AutoPyRef(AutoPyRef&& other) = default; AutoPyRef& operator=(const AutoPyRef& other) { if(_pyobj==other._pyobj) return *this; release(); _pyobj=other._pyobj; Py_XINCREF(_pyobj); return *this; } @@ -55,3 +55,12 @@ public: AutoPyRefGilSafe(PyObject *pyobj=nullptr):AutoPyRef(pyobj) { } ~AutoPyRefGilSafe() { AutoGIL agil; release(); } }; + +class AutoPyYielder +{ +private: + PyThreadState *_save = nullptr; +public: + AutoPyYielder() { _save = PyEval_SaveThread(); } + ~AutoPyYielder() { PyEval_RestoreThread(_save); } +}; diff --git a/src/Container/Container_i.cxx b/src/Container/Container_i.cxx index 872e161ab..0ad306bb0 100644 --- a/src/Container/Container_i.cxx +++ b/src/Container/Container_i.cxx @@ -156,7 +156,7 @@ Abstract_Engines_Container_i::Abstract_Engines_Container_i (CORBA::ORB_ptr orb, { _pid = (long)getpid(); - if(ns) + if( isServantAloneInProcess ) ActSigIntHandler() ; _argc = argc ; @@ -708,6 +708,24 @@ CORBA::Long Abstract_Engines_Container_i::getTotalPhysicalMemoryInUseByMe() */ //============================================================================= void Abstract_Engines_Container_i::Shutdown() +{ + ShutdownCommonPart(); + if(_isServantAloneInProcess) + { + MESSAGE("Effective Shutdown of container Begins..."); + try + { + if(!CORBA::is_nil(_orb)) + _orb->shutdown(0); + } + catch(...) + { + } + MESSAGE("Effective Shutdown of container Ends..."); + } +} + +void Abstract_Engines_Container_i::ShutdownCommonPart() { MESSAGE("Engines_Container_i::Shutdown()"); @@ -734,7 +752,7 @@ void Abstract_Engines_Container_i::Shutdown() } } _listInstances_map.clear(); - + MESSAGE("Engines_Container_i::Shutdown() -- step 2"); // NS unregistering may throw in SSL mode if master process hosting SALOME_Embedded_NamingService servant has vanished // In this case it's skip it and still continue. try @@ -745,19 +763,28 @@ void Abstract_Engines_Container_i::Shutdown() catch(...) { } - // - this->cleanAllPyScripts(); - // + MESSAGE("Engines_Container_i::Shutdown() -- step 3"); + try { - AutoGIL gstate; - AutoPyRef result = PyObject_CallMethod(_pyCont, (char*)"shutdownPy", (char*)"",nullptr); + this->cleanAllPyScripts(); + // + { + AutoGIL gstate; + AutoPyRef result = PyObject_CallMethod(_pyCont, (char*)"shutdownPy", (char*)"",nullptr); + } } - // - if(_isServantAloneInProcess) + catch(...) { - MESSAGE("Effective Shutdown of container Begins..."); - if(!CORBA::is_nil(_orb)) - _orb->shutdown(0); + } + MESSAGE("Engines_Container_i::Shutdown() -- step 4"); +} + +void Abstract_Engines_Container_i::ShutdownNow() +{ + ShutdownCommonPart();if(_isServantAloneInProcess) + { + AutoGIL gstate; + AutoPyRef result = PyObject_CallMethod(_pyCont, (char*)"killMe", (char*)"",nullptr); } } diff --git a/src/Container/SALOME_Container.py b/src/Container/SALOME_Container.py index 1fa1d41d0..66113499a 100644 --- a/src/Container/SALOME_Container.py +++ b/src/Container/SALOME_Container.py @@ -186,6 +186,10 @@ class SALOME_Container_i: #self._log.destroy()# TODO : choose to destroy perf report or not. For the moment we keep the report pass + def killMe(self): + import signal + os.kill( os.getpid() , signal.SIGTERM) + def setLogFileName(self, logFileName): logging.debug("setLogFileName {} PID = {}".format(logFileName,os.getpid())) if getSSLMode(): diff --git a/src/Container/SALOME_ContainerManager.cxx b/src/Container/SALOME_ContainerManager.cxx index d3d36bb70..66cd8fd09 100644 --- a/src/Container/SALOME_ContainerManager.cxx +++ b/src/Container/SALOME_ContainerManager.cxx @@ -241,9 +241,9 @@ void SALOME_ContainerManager::SetDeltaTimeBetweenCPUMemMeasureInMilliSecond(CORB */ //============================================================================= -void SALOME_ContainerManager::ShutdownContainers() +void SALOME_ContainerManager::ShutdownContainersGeneric(std::function funcToBeCalledOnContainer) { - MESSAGE("ShutdownContainers"); + MESSAGE("ShutdownContainersGeneric"); if(!_NS) return ; SALOME::Session_var session = SALOME::Session::_nil(); @@ -289,11 +289,12 @@ void SALOME_ContainerManager::ShutdownContainers() Engines::Container_var cont=Engines::Container::_narrow(obj); if(!CORBA::is_nil(cont)) { - MESSAGE("ShutdownContainers: " << (*iter)); - cont->Shutdown(); + MESSAGE("ShutdownContainersGeneric: " << (*iter)); + funcToBeCalledOnContainer( cont ); + MESSAGE("ShutdownContainersGeneric: after call of shutdown" << (*iter)); } else - MESSAGE("ShutdownContainers: no container ref for " << (*iter)); + MESSAGE("ShutdownContainersGeneric: no container ref for " << (*iter)); } catch(CORBA::SystemException& e) { @@ -311,6 +312,26 @@ void SALOME_ContainerManager::ShutdownContainers() } } +void SALOME_ContainerManager::ShutdownContainers() +{ + this->ShutdownContainersGeneric( [](Engines::Container_ptr cont) { cont->Shutdown(); } ); +} + +void SALOME_ContainerManager::ShutdownContainersNow() +{ + this->ShutdownContainersGeneric( [](Engines::Container_ptr cont) + { + try + { + cont->ShutdownNow(); + } + catch(...) + { + } + } + ); +} + void SALOME_ContainerManager::SetOverrideEnvForContainers(const Engines::KeyValDict& env) { this->_override_env.clear(); diff --git a/src/Container/SALOME_ContainerManager.hxx b/src/Container/SALOME_ContainerManager.hxx index c1d33f9bf..330d3ed7c 100644 --- a/src/Container/SALOME_ContainerManager.hxx +++ b/src/Container/SALOME_ContainerManager.hxx @@ -35,6 +35,7 @@ #include #include #include +#include #include class SALOME_NamingService_Abstract; @@ -52,6 +53,8 @@ public: void ShutdownContainers() override; + void ShutdownContainersNow() override; + void SetOverrideEnvForContainers(const Engines::KeyValDict& env) override; Engines::KeyValDict *GetOverrideEnvForContainers() override; @@ -77,6 +80,10 @@ public: static const char *_ContainerManagerNameInNS; +private: + + void ShutdownContainersGeneric(std::function funcToBeCalledOnContainer); + protected: // C++ methods Engines::Container_ptr diff --git a/src/Container/SALOME_Container_SignalsHandler.cxx b/src/Container/SALOME_Container_SignalsHandler.cxx index f3539d41a..55b548428 100644 --- a/src/Container/SALOME_Container_SignalsHandler.cxx +++ b/src/Container/SALOME_Container_SignalsHandler.cxx @@ -39,6 +39,7 @@ void HandleServerSideSignals(CORBA::ORB_ptr theORB) // CASCatch_SignalsHandler aSignalsHandler; try { theORB->run(); + INFOS("ORB run finished..."); // CCRT porting // }catch(CORBA::SystemException&){ // Handle(Standard_Failure) aFail = Standard_Failure::Caught(); diff --git a/src/Container/SALOME_Container_i.hxx b/src/Container/SALOME_Container_i.hxx index a86c22af2..9f67a52ce 100644 --- a/src/Container/SALOME_Container_i.hxx +++ b/src/Container/SALOME_Container_i.hxx @@ -124,7 +124,8 @@ public: void verbosity(bool& activated, CORBA::String_out level) override; void setVerbosity(bool activated, const char *level) override; - virtual void Shutdown(); + void Shutdown() override; + void ShutdownNow() override; char *getHostName(); CORBA::Long getPID(); //! Kill current container @@ -170,6 +171,8 @@ public: PortableServer::ObjectId *getCORBAId() const { return _id; } public: static const int DFT_TIME_INTERVAL_BTW_MEASURE; +private: + void ShutdownCommonPart(); protected: static std::map _cntInstances_map; static std::map _library_map; // library names, loaded diff --git a/src/KERNEL_PY/__init__.py b/src/KERNEL_PY/__init__.py index 4446fdb60..615332500 100644 --- a/src/KERNEL_PY/__init__.py +++ b/src/KERNEL_PY/__init__.py @@ -272,6 +272,7 @@ def salome_init_without_session(path=None, embedded=False, iorfakensfile=None): type(logm).Fetch = LogManagerFetch type(logm).DumpInFile = LogManagerDumpInFile type(logm).LaunchMonitoringDumpFile = LogManagerLaunchMonitoringDumpFile + type(logm).FinalFetchBeforeDying = LogManagerFinalFetchBeforeDying type(logm).GetLatestMonitoringDumpFile = LogManagerGetLatestMonitoringDumpFile type(logm).DumpIORInFile = LogManagerDumpIORInFile # @@ -283,6 +284,12 @@ def salome_init_without_session(path=None, embedded=False, iorfakensfile=None): with open(iorfakensfile,"w") as iorfakensf: iorfakensf.write(NamingService.IOROfNS()) +CM_NAME_IN_NS = "/ContainerManager" +RM_NAME_IN_NS = "/ResourcesManager" +DSM_NAME_IN_NS = "/DataServerManager" +ESM_NAME_IN_NS = "/ExternalServers" +LOGM_NAME_IN_NS = "/LogManager" + def salome_init_without_session_attached(path=None, embedded=False): """ Configuration SSL inside a python interpretor launched in the SALOME_Container_No_NS_Serv. @@ -297,25 +304,20 @@ def salome_init_without_session_attached(path=None, embedded=False): import KernelBasis nsAbroad = orb.string_to_object( KernelBasis.getIOROfEmbeddedNS() ) import SALOME - CM_NAME_IN_NS = "/ContainerManager" cm = orb.string_to_object( nsAbroad.Resolve(CM_NAME_IN_NS).decode() ) type(cm).SetOverrideEnvForContainersSimple = ContainerManagerSetOverrideEnvForContainersSimple naming_service.Register(cm,CM_NAME_IN_NS) - RM_NAME_IN_NS = "/ResourcesManager" rm = orb.string_to_object( nsAbroad.Resolve(RM_NAME_IN_NS).decode() ) naming_service.Register(rm,RM_NAME_IN_NS) # from LifeCycleCORBA import LifeCycleCORBASSL lcc = LifeCycleCORBASSL() - DSM_NAME_IN_NS = "/DataServerManager" dsm = orb.string_to_object( nsAbroad.Resolve(DSM_NAME_IN_NS).decode() ) naming_service.Register(dsm,DSM_NAME_IN_NS) # - ESM_NAME_IN_NS = "/ExternalServers" esm = orb.string_to_object( nsAbroad.Resolve(ESM_NAME_IN_NS).decode() ) naming_service.Register(esm,ESM_NAME_IN_NS) # - LOGM_NAME_IN_NS = "/LogManager" logm = orb.string_to_object( nsAbroad.Resolve(LOGM_NAME_IN_NS).decode() ) naming_service.Register(logm,LOGM_NAME_IN_NS) @@ -567,6 +569,12 @@ def LogManagerLoadFromIORFile( iorFile ): tempFileName = f.name return LoadAndWrite( logm, tempFileName ) +def LogManagerFinalFetchBeforeDying(self): + import shutil + a,b = self.getFileNamePairOfLogger() + self.DumpInFile( b ) + shutil.move( b, a) + def LogManagerGetLatestMonitoringDumpFile(self): import shutil import logging @@ -580,14 +588,16 @@ def LogManagerGetLatestMonitoringDumpFile(self): logging.debug("LogManagerGetLatestMonitoringDumpFile SITUATION A") if os.path.exists( b ): os.remove( b ) + self.FinalFetchBeforeDying() return a if lastVersion == b: logging.debug("LogManagerGetLatestMonitoringDumpFile SITUATION B") if os.path.exists( b ): shutil.move( b, a) + self.FinalFetchBeforeDying() return a logging.warning("in LogManagerGetLatestMonitoringDumpFile an unexpected situation araises.") return "" #to expose all objects to pydoc -__all__=dir() +__all__ = dir() diff --git a/src/NamingService/NamingService.i b/src/NamingService/NamingService.i index f63aba017..308588a3f 100644 --- a/src/NamingService/NamingService.i +++ b/src/NamingService/NamingService.i @@ -141,6 +141,15 @@ def NamingService_DumpIORInFile(cls,iorFileName): with open( iorFileName, "w" ) as f: f.write( cls.IOROfNS() ) NamingService.DumpIORInFile = classmethod(NamingService_DumpIORInFile) +def NamingService_LoadIORInFile(cls,iorFileName): + import Engines + import CORBA + orb=CORBA.ORB_init(['']) + with open( iorFileName ) as f: + ior = f.read() + ref = orb.string_to_object(ior) + return ref +NamingService.LoadIORInFile = classmethod( NamingService_LoadIORInFile ) def NamingService_KillContainersInFile(cls,logFileName): import Engines import CORBA -- 2.39.2