1 // SALOME Container : implementation of container and engine for Kernel
3 // Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
24 // File : Container_i.cxx
25 // Author : Paul RASCLE, EDF - MARC TAJCHMAN, CEA
29 //#define private public
43 #include "utilities.h"
44 #include <SALOMEconfig.h>
46 #include CORBA_SERVER_HEADER(SALOME_Component)
48 //#include <SALOME_Component.hh>
50 #include <pthread.h> // must be before Python.h !
51 #include "SALOME_Container_i.hxx"
52 #include "SALOME_Component_i.hxx"
53 #include "SALOME_FileRef_i.hxx"
54 #include "SALOME_FileTransfer_i.hxx"
55 #include "SALOME_NamingService.hxx"
59 #include "Container_init_python.hxx"
63 bool _Sleeping = false ;
65 // // Needed by multi-threaded Python --- Supervision
70 // Containers with name FactoryServer are started via rsh in LifeCycleCORBA
71 // Other Containers are started via start_impl of FactoryServer
73 extern "C" {void ActSigIntHandler() ; }
75 extern "C" {void SigIntHandler(int, siginfo_t *, void *) ; }
77 extern "C" {void SigIntHandler( int ) ; }
81 map<std::string, int> Engines_Container_i::_cntInstances_map;
82 map<std::string, void *> Engines_Container_i::_library_map;
83 map<std::string, void *> Engines_Container_i::_toRemove_map;
84 omni_mutex Engines_Container_i::_numInstanceMutex ;
86 //=============================================================================
88 * Default constructor, not for use
90 //=============================================================================
92 Engines_Container_i::Engines_Container_i () :
97 //=============================================================================
101 //=============================================================================
103 Engines_Container_i::Engines_Container_i (CORBA::ORB_ptr orb,
104 PortableServer::POA_var poa,
105 char *containerName ,
106 int argc , char* argv[],
108 bool isServantAloneInProcess
110 _numInstance(0),_isServantAloneInProcess(isServantAloneInProcess)
112 _pid = (long)getpid();
120 string hostname = GetHostname();
121 MESSAGE(hostname << " " << getpid() << " Engines_Container_i starting argc "
122 << _argc << " Thread " << pthread_self() ) ;
127 MESSAGE(" argv" << i << " " << _argv[ i ]) ;
133 INFOS("SALOME_Container usage : SALOME_Container ServerName");
137 _isSupervContainer = false;
138 if (strcmp(argv[1],"SuperVisionContainer") == 0) _isSupervContainer = true;
140 if (_isSupervContainer)
146 _orb = CORBA::ORB::_duplicate(orb) ;
147 _poa = PortableServer::POA::_duplicate(poa) ;
149 // Pour les containers paralleles: il ne faut pas enregistrer et activer
150 // le container generique, mais le container specialise
154 _id = _poa->activate_object(this);
155 _NS = new SALOME_NamingService();
156 _NS->init_orb( CORBA::ORB::_duplicate(_orb) ) ;
157 CORBA::Object_var obj=_poa->id_to_reference(*_id);
158 Engines::Container_var pCont
159 = Engines::Container::_narrow(obj);
161 _containerName = _NS->BuildContainerNameForNS(containerName,
163 SCRUTE(_containerName);
164 _NS->Register(pCont, _containerName.c_str());
165 MESSAGE("Engines_Container_i::Engines_Container_i : Container name "
169 // import SALOME_Container
170 // pycont = SALOME_Container.SALOME_Container_i(containerIORStr)
172 CORBA::String_var sior = _orb->object_to_string(pCont);
173 string myCommand="pyCont = SALOME_Container.SALOME_Container_i('";
174 myCommand += _containerName + "','";
179 if (!_isSupervContainer)
182 //Py_ACQUIRE_NEW_THREAD;
183 PyEval_AcquireLock();
184 /* It should not be possible for more than one thread state
185 to be used for a thread.*/
186 PyThreadState *myTstate = PyGILState_GetThisThreadState();
187 // if no thread state defined
189 myTstate = PyThreadState_New(KERNEL_PYTHON::_interp);
190 PyThreadState *myoldTstate = PyThreadState_Swap(myTstate);
192 Py_ACQUIRE_NEW_THREAD;
196 // mpv: this is temporary solution: there is a unregular crash if not
199 // first element is the path to Registry.dll, but it's wrong
200 PyRun_SimpleString("import sys\n");
201 PyRun_SimpleString("sys.path = sys.path[1:]\n");
203 PyRun_SimpleString("import SALOME_Container\n");
204 PyRun_SimpleString((char*)myCommand.c_str());
205 Py_RELEASE_NEW_THREAD;
208 fileTransfer_i* aFileTransfer = new fileTransfer_i();
209 _fileTransfer = Engines::fileTransfer::_narrow(aFileTransfer->_this());
213 //=============================================================================
217 //=============================================================================
219 Engines_Container_i::~Engines_Container_i()
221 MESSAGE("Container_i::~Container_i()");
225 //=============================================================================
227 * CORBA attribute: Container name (see constructor)
229 //=============================================================================
231 char* Engines_Container_i::name()
233 return CORBA::string_dup(_containerName.c_str()) ;
236 //=============================================================================
238 * CORBA method: Get the hostName of the Container (without domain extensions)
240 //=============================================================================
242 char* Engines_Container_i::getHostName()
244 string s = GetHostname();
245 // MESSAGE("Engines_Container_i::getHostName " << s);
246 return CORBA::string_dup(s.c_str()) ;
249 //=============================================================================
251 * CORBA method: Get the PID (process identification) of the Container
253 //=============================================================================
255 CORBA::Long Engines_Container_i::getPID()
257 return (CORBA::Long)getpid();
260 //=============================================================================
262 * CORBA method: check if servant is still alive
264 //=============================================================================
266 void Engines_Container_i::ping()
268 MESSAGE("Engines_Container_i::ping() pid "<< getpid());
271 //=============================================================================
273 * CORBA method, oneway: Server shutdown.
274 * - Container name removed from naming service,
275 * - servant deactivation,
276 * - orb shutdown if no other servants in the process
278 //=============================================================================
280 void Engines_Container_i::Shutdown()
282 MESSAGE("Engines_Container_i::Shutdown()");
284 /* For each component contained in this container
285 * tell it to self-destroy
287 std::map<std::string, Engines::Component_var>::iterator itm;
288 for (itm = _listInstances_map.begin(); itm != _listInstances_map.end(); itm++)
289 itm->second->destroy();
291 _NS->Destroy_FullDirectory(_containerName.c_str());
292 _NS->Destroy_Name(_containerName.c_str());
294 //_poa->deactivate_object(*_id);
295 if(_isServantAloneInProcess)
297 MESSAGE("Effective Shutdown of container Begins...");
298 LocalTraceBufferPool* bp1 = LocalTraceBufferPool::instance();
299 bp1->deleteInstance(bp1);
305 //=============================================================================
307 * CORBA method: load a new component class (Python or C++ implementation)
308 * \param componentName like COMPONENT
309 * try to make a Python import of COMPONENT,
310 * then a lib open of libCOMPONENTEngine.so
311 * \return true if dlopen successfull or already done, false otherwise
313 //=============================================================================
316 Engines_Container_i::load_component_Library(const char* componentName)
319 string aCompName = componentName;
321 // --- try dlopen C++ component
324 string impl_name = string ("lib") + aCompName + string("Engine.so");
326 string impl_name = aCompName + string("Engine.dll");
330 _numInstanceMutex.lock(); // lock to be alone
331 // (see decInstanceCnt, finalize_removal))
332 if (_toRemove_map[impl_name]) _toRemove_map.erase(impl_name);
333 if (_library_map[impl_name])
335 MESSAGE("Library " << impl_name << " already loaded");
336 _numInstanceMutex.unlock();
342 handle = dlopen( impl_name.c_str() , RTLD_LAZY ) ;
345 handle = LoadLibrary( impl_name.c_str() );
350 _library_map[impl_name] = handle;
351 _numInstanceMutex.unlock();
356 INFOS( "Can't load shared library: " << impl_name );
358 INFOS("error dlopen: " << dlerror());
361 _numInstanceMutex.unlock();
363 // --- try import Python component
365 INFOS("try import Python component "<<componentName);
366 if (_isSupervContainer)
368 INFOS("Supervision Container does not support Python Component Engines");
371 if (_library_map[aCompName])
373 return true; // Python Component, already imported
377 Py_ACQUIRE_NEW_THREAD;
378 PyObject *mainmod = PyImport_AddModule("__main__");
379 PyObject *globals = PyModule_GetDict(mainmod);
380 PyObject *pyCont = PyDict_GetItemString(globals, "pyCont");
381 PyObject *result = PyObject_CallMethod(pyCont,
384 int ret= PyInt_AsLong(result);
386 Py_RELEASE_NEW_THREAD;
388 if (ret) // import possible: Python component
390 _numInstanceMutex.lock() ; // lock to be alone (stl container write)
391 _library_map[aCompName] = (void *)pyCont; // any non O value OK
392 _numInstanceMutex.unlock() ;
393 MESSAGE("import Python: "<<aCompName<<" OK");
400 //=============================================================================
402 * CORBA method: Creates a new servant instance of a component.
403 * The servant registers itself to naming service and Registry.
404 * \param genericRegisterName Name of the component instance to register
405 * in Registry & Name Service (without _inst_n suffix)
406 * \param studyId 0 for multiStudy instance,
407 * study Id (>0) otherwise
408 * \return a loaded component
410 //=============================================================================
412 Engines::Component_ptr
413 Engines_Container_i::create_component_instance(const char*genericRegisterName,
418 INFOS("studyId must be > 0 for mono study instance, =0 for multiStudy");
419 return Engines::Component::_nil() ;
422 Engines::Component_var iobject = Engines::Component::_nil() ;
424 string aCompName = genericRegisterName;
425 if (_library_map[aCompName]) // Python component
427 if (_isSupervContainer)
429 INFOS("Supervision Container does not support Python Component Engines");
430 return Engines::Component::_nil();
432 _numInstanceMutex.lock() ; // lock on the instance number
434 int numInstance = _numInstance ;
435 _numInstanceMutex.unlock() ;
438 sprintf( aNumI , "%d" , numInstance ) ;
439 string instanceName = aCompName + "_inst_" + aNumI ;
440 string component_registerName =
441 _containerName + "/" + instanceName;
443 Py_ACQUIRE_NEW_THREAD;
444 PyObject *mainmod = PyImport_AddModule("__main__");
445 PyObject *globals = PyModule_GetDict(mainmod);
446 PyObject *pyCont = PyDict_GetItemString(globals, "pyCont");
447 PyObject *result = PyObject_CallMethod(pyCont,
448 "create_component_instance",
451 instanceName.c_str(),
453 string iors = PyString_AsString(result);
455 Py_RELEASE_NEW_THREAD;
459 CORBA::Object_var obj = _orb->string_to_object(iors.c_str());
460 iobject = Engines::Component::_narrow( obj ) ;
462 return iobject._retn();
468 string impl_name = string ("lib") + genericRegisterName +string("Engine.so");
470 string impl_name = genericRegisterName +string("Engine.dll");
472 void* handle = _library_map[impl_name];
475 INFOS("shared library " << impl_name <<"must be loaded before instance");
476 return Engines::Component::_nil() ;
480 iobject = createInstance(genericRegisterName,
483 return iobject._retn();
487 //=============================================================================
489 * CORBA method: Finds a servant instance of a component
490 * \param registeredName Name of the component in Registry or Name Service,
491 * without instance suffix number
492 * \param studyId 0 if instance is not associated to a study,
493 * >0 otherwise (== study id)
494 * \return the first instance found with same studyId
496 //=============================================================================
498 Engines::Component_ptr
499 Engines_Container_i::find_component_instance( const char* registeredName,
502 Engines::Component_var anEngine = Engines::Component::_nil();
503 map<string,Engines::Component_var>::iterator itm =_listInstances_map.begin();
504 while (itm != _listInstances_map.end())
506 string instance = (*itm).first;
508 if (instance.find(registeredName) == 0)
510 anEngine = (*itm).second;
511 if (studyId == anEngine->getStudyId())
513 return anEngine._retn();
518 return anEngine._retn();
521 //=============================================================================
523 * CORBA method: find or create an instance of the component (servant),
524 * load a new component class (dynamic library) if required,
525 * ---- FOR COMPATIBILITY WITH 2.2 ----
526 * ---- USE ONLY FOR MULTISTUDY INSTANCES ! --------
527 * The servant registers itself to naming service and Registry.
528 * \param genericRegisterName Name of the component to register
529 * in Registry & Name Service
530 * \param componentName Name of the constructed library of the component
531 * \return a loaded component
533 //=============================================================================
535 Engines::Component_ptr
536 Engines_Container_i::load_impl( const char* genericRegisterName,
537 const char* componentName )
539 string impl_name = string ("lib") + genericRegisterName +string("Engine.so");
540 Engines::Component_var iobject = Engines::Component::_nil() ;
541 if (load_component_Library(genericRegisterName))
542 iobject = find_or_create_instance(genericRegisterName, impl_name);
543 return iobject._retn();
547 //=============================================================================
549 * CORBA method: Stops the component servant, and deletes all related objects
550 * \param component_i Component to be removed
552 //=============================================================================
554 void Engines_Container_i::remove_impl(Engines::Component_ptr component_i)
556 ASSERT(! CORBA::is_nil(component_i));
557 string instanceName = component_i->instanceName() ;
558 MESSAGE("unload component " << instanceName);
559 _numInstanceMutex.lock() ; // lock to be alone (stl container write)
560 _listInstances_map.erase(instanceName);
561 _numInstanceMutex.unlock() ;
562 component_i->destroy() ;
563 _NS->Destroy_Name(instanceName.c_str());
566 //=============================================================================
568 * CORBA method: Discharges unused libraries from the container.
570 //=============================================================================
572 void Engines_Container_i::finalize_removal()
574 MESSAGE("finalize unload : dlclose");
575 _numInstanceMutex.lock(); // lock to be alone
576 // (see decInstanceCnt, load_component_Library)
577 map<string, void *>::iterator ith;
578 for (ith = _toRemove_map.begin(); ith != _toRemove_map.end(); ith++)
580 void *handle = (*ith).second;
581 string impl_name= (*ith).first;
586 // dlclose(handle); // SALOME unstable after ...
587 // _library_map.erase(impl_name);
590 _toRemove_map.clear();
591 _numInstanceMutex.unlock();
594 //=============================================================================
596 * CORBA method: Kill the container process with exit(0).
597 * To remove : never returns !
599 //=============================================================================
601 bool Engines_Container_i::Kill_impl()
603 MESSAGE("Engines_Container_i::Kill() pid "<< getpid() << " containerName "
604 << _containerName.c_str() << " machineName "
605 << GetHostname().c_str());
606 INFOS("===============================================================");
607 INFOS("= REMOVE calls to Kill_impl in C++ container =");
608 INFOS("===============================================================");
614 //=============================================================================
616 * CORBA method: get or create a fileRef object associated to a local file
617 * (a file on the computer on which runs the container server), which stores
618 * a list of (machine, localFileName) corresponding to copies already done.
620 * \param origFileName absolute path for a local file to copy on other
622 * \return a fileRef object associated to the file.
624 //=============================================================================
627 Engines_Container_i::createFileRef(const char* origFileName)
629 string origName(origFileName);
630 Engines::fileRef_var theFileRef = Engines::fileRef::_nil();
632 if (origName[0] != '/')
634 INFOS("path of file to copy must be an absolute path begining with '/'");
635 return Engines::fileRef::_nil();
638 if (CORBA::is_nil(_fileRef_map[origName]))
640 CORBA::Object_var obj=_poa->id_to_reference(*_id);
641 Engines::Container_var pCont = Engines::Container::_narrow(obj);
642 fileRef_i* aFileRef = new fileRef_i(pCont, origFileName);
643 theFileRef = Engines::fileRef::_narrow(aFileRef->_this());
644 _numInstanceMutex.lock() ; // lock to be alone (stl container write)
645 _fileRef_map[origName] = theFileRef;
646 _numInstanceMutex.unlock() ;
649 theFileRef = Engines::fileRef::_duplicate(_fileRef_map[origName]);
650 ASSERT(! CORBA::is_nil(theFileRef));
651 return theFileRef._retn();
654 //=============================================================================
657 * \return a reference to the fileTransfer object
659 //=============================================================================
661 Engines::fileTransfer_ptr
662 Engines_Container_i::getFileTransfer()
664 Engines::fileTransfer_var aFileTransfer
665 = Engines::fileTransfer::_duplicate(_fileTransfer);
666 return aFileTransfer._retn();
670 //=============================================================================
672 * C++ method: Finds an already existing servant instance of a component, or
673 * create an instance.
674 * ---- USE ONLY FOR MULTISTUDY INSTANCES ! --------
675 * \param genericRegisterName Name of the component instance to register
676 * in Registry & Name Service,
677 * (without _inst_n suffix, like "COMPONENT")
678 * \param componentLibraryName like "libCOMPONENTEngine.so"
679 * \return a loaded component
681 * example with names:
682 * aGenRegisterName = COMPONENT (= first argument)
683 * impl_name = libCOMPONENTEngine.so (= second argument)
684 * _containerName = /Containers/cli76ce/FactoryServer
685 * factoryName = COMPONENTEngine_factory
686 * component_registerBase = /Containers/cli76ce/FactoryServer/COMPONENT
688 * instanceName = COMPONENT_inst_1
689 * component_registerName = /Containers/cli76ce/FactoryServer/COMPONENT_inst_1
691 //=============================================================================
693 Engines::Component_ptr
694 Engines_Container_i::find_or_create_instance(string genericRegisterName,
695 string componentLibraryName)
697 string aGenRegisterName = genericRegisterName;
698 string impl_name = componentLibraryName;
699 void* handle = _library_map[impl_name];
702 INFOS("shared library " << impl_name <<"must be loaded before instance");
703 return Engines::Component::_nil() ;
707 // --- find a registered instance in naming service, or create
709 string component_registerBase =
710 _containerName + "/" + aGenRegisterName;
711 Engines::Component_var iobject = Engines::Component::_nil() ;
714 CORBA::Object_var obj =
715 _NS->ResolveFirst( component_registerBase.c_str());
716 if ( CORBA::is_nil( obj ) )
718 iobject = createInstance(genericRegisterName,
720 0); // force multiStudy instance here !
724 iobject = Engines::Component::_narrow( obj ) ;
725 Engines_Component_i *servant =
726 dynamic_cast<Engines_Component_i*>
727 (_poa->reference_to_servant(iobject));
729 int studyId = servant->getStudyId();
730 ASSERT (studyId >= 0);
731 if (studyId == 0) // multiStudy instance, OK
734 MESSAGE(component_registerBase.c_str()<<" already bound");
736 else // monoStudy instance: NOK
738 iobject = Engines::Component::_nil();
739 INFOS("load_impl & find_component_instance methods "
740 << "NOT SUITABLE for mono study components");
746 INFOS( "Container_i::load_impl catched" ) ;
748 return iobject._retn();
752 //=============================================================================
754 * C++ method: create a servant instance of a component.
755 * \param genericRegisterName Name of the component instance to register
756 * in Registry & Name Service,
757 * (without _inst_n suffix, like "COMPONENT")
758 * \param handle loaded library handle
759 * \param studyId 0 for multiStudy instance,
760 * study Id (>0) otherwise
761 * \return a loaded component
763 * example with names:
764 * aGenRegisterName = COMPONENT (= first argument)
765 * _containerName = /Containers/cli76ce/FactoryServer
766 * factoryName = COMPONENTEngine_factory
767 * component_registerBase = /Containers/cli76ce/FactoryServer/COMPONENT
768 * instanceName = COMPONENT_inst_1
769 * component_registerName = /Containers/cli76ce/FactoryServer/COMPONENT_inst_1
771 //=============================================================================
773 Engines::Component_ptr
774 Engines_Container_i::createInstance(string genericRegisterName,
778 // --- find the factory
780 string aGenRegisterName = genericRegisterName;
781 string factory_name = aGenRegisterName + string("Engine_factory");
782 SCRUTE(factory_name) ;
784 typedef PortableServer::ObjectId * (*FACTORY_FUNCTION)
786 PortableServer::POA_ptr,
787 PortableServer::ObjectId *,
792 FACTORY_FUNCTION Component_factory = (FACTORY_FUNCTION)dlsym( handle, factory_name.c_str() );
794 FACTORY_FUNCTION Component_factory = (FACTORY_FUNCTION)GetProcAddress( (HINSTANCE)handle, factory_name.c_str() );
797 if ( !Component_factory )
799 INFOS( "Can't resolve symbol: " + factory_name );
803 return Engines::Component::_nil() ;
806 // --- create instance
808 Engines::Component_var iobject = Engines::Component::_nil() ;
812 _numInstanceMutex.lock() ; // lock on the instance number
814 int numInstance = _numInstance ;
815 _numInstanceMutex.unlock() ;
818 sprintf( aNumI , "%d" , numInstance ) ;
819 string instanceName = aGenRegisterName + "_inst_" + aNumI ;
820 string component_registerName =
821 _containerName + "/" + instanceName;
823 // --- Instanciate required CORBA object
825 PortableServer::ObjectId *id ; //not owner, do not delete (nore use var)
826 id = (Component_factory) ( _orb, _poa, _id, instanceName.c_str(),
827 aGenRegisterName.c_str() ) ;
829 return iobject._retn();
831 // --- get reference & servant from id
833 CORBA::Object_var obj = _poa->id_to_reference(*id);
834 iobject = Engines::Component::_narrow( obj ) ;
836 Engines_Component_i *servant =
837 dynamic_cast<Engines_Component_i*>(_poa->reference_to_servant(iobject));
839 //SCRUTE(servant->pd_refCount);
840 servant->_remove_ref(); // compensate previous id_to_reference
841 //SCRUTE(servant->pd_refCount);
842 _numInstanceMutex.lock() ; // lock to be alone (stl container write)
843 _listInstances_map[instanceName] = iobject;
844 _cntInstances_map[aGenRegisterName] += 1;
845 _numInstanceMutex.unlock() ;
846 SCRUTE(aGenRegisterName);
847 SCRUTE(_cntInstances_map[aGenRegisterName]);
848 //SCRUTE(servant->pd_refCount);
849 bool ret_studyId = servant->setStudyId(studyId);
852 // --- register the engine under the name
853 // containerName(.dir)/instanceName(.object)
855 _NS->Register( iobject , component_registerName.c_str() ) ;
856 MESSAGE( component_registerName.c_str() << " bound" ) ;
860 INFOS( "Container_i::createInstance exception catched" ) ;
862 return iobject._retn();
865 //=============================================================================
869 //=============================================================================
871 void Engines_Container_i::decInstanceCnt(string genericRegisterName)
873 string aGenRegisterName =genericRegisterName;
874 MESSAGE("Engines_Container_i::decInstanceCnt " << aGenRegisterName);
875 ASSERT(_cntInstances_map[aGenRegisterName] > 0);
876 _numInstanceMutex.lock(); // lock to be alone
877 // (see finalize_removal, load_component_Library)
878 _cntInstances_map[aGenRegisterName] -= 1;
879 SCRUTE(_cntInstances_map[aGenRegisterName]);
880 if (_cntInstances_map[aGenRegisterName] == 0)
883 Engines_Component_i::GetDynLibraryName(aGenRegisterName.c_str());
885 void* handle = _library_map[impl_name];
887 _toRemove_map[impl_name] = handle;
889 _numInstanceMutex.unlock();
892 //=============================================================================
894 * Retrieves only with container naming convention if it is a python container
896 //=============================================================================
898 bool Engines_Container_i::isPythonContainer(const char* ContainerName)
901 int len=strlen(ContainerName);
903 if(strcmp(ContainerName+len-2,"Py")==0)
908 //=============================================================================
912 //=============================================================================
914 void ActSigIntHandler()
917 struct sigaction SigIntAct ;
918 SigIntAct.sa_sigaction = &SigIntHandler ;
919 SigIntAct.sa_flags = SA_SIGINFO ;
922 // DEBUG 03.02.2005 : the first parameter of sigaction is not a mask of signals
923 // (SIGINT | SIGUSR1) :
924 // it must be only one signal ===> one call for SIGINT
925 // and an other one for SIGUSR1
928 if ( sigaction( SIGINT , &SigIntAct, NULL ) )
930 perror("SALOME_Container main ") ;
933 if ( sigaction( SIGUSR1 , &SigIntAct, NULL ) )
935 perror("SALOME_Container main ") ;
938 if ( sigaction( SIGUSR2 , &SigIntAct, NULL ) )
940 perror("SALOME_Container main ") ;
944 //PAL9042 JR : during the execution of a Signal Handler (and of methods called through Signal Handlers)
945 // use of streams (and so on) should never be used because :
946 // streams of C++ are naturally thread-safe and use pthread_mutex_lock ===>
947 // A stream operation may be interrupted by a signal and if the Handler use stream we
948 // may have a "Dead-Lock" ===HangUp
949 //==INFOS is commented
950 // INFOS(pthread_self() << "SigIntHandler activated") ;
953 signal( SIGINT, SigIntHandler );
954 signal( SIGUSR1, SigIntHandler );
960 void CallCancelThread() ;
963 void SigIntHandler(int what ,
964 siginfo_t * siginfo ,
967 //PAL9042 JR : during the execution of a Signal Handler (and of methods called through Signal Handlers)
968 // use of streams (and so on) should never be used because :
969 // streams of C++ are naturally thread-safe and use pthread_mutex_lock ===>
970 // A stream operation may be interrupted by a signal and if the Handler use stream we
971 // may have a "Dead-Lock" ===HangUp
972 //==MESSAGE is commented
973 // MESSAGE(pthread_self() << "SigIntHandler what " << what << endl
974 // << " si_signo " << siginfo->si_signo << endl
975 // << " si_code " << siginfo->si_code << endl
976 // << " si_pid " << siginfo->si_pid) ;
981 // MESSAGE("SigIntHandler END sleeping.") ;
987 if ( siginfo->si_signo == SIGUSR1 )
991 else if ( siginfo->si_signo == SIGUSR2 )
998 // MESSAGE("SigIntHandler BEGIN sleeping.") ;
1005 // MESSAGE("SigIntHandler LEAVE sleeping after " << count << " s.") ;
1011 void SigIntHandler( int what )
1013 MESSAGE( pthread_self() << "SigIntHandler what " << what << endl );
1017 MESSAGE("SigIntHandler END sleeping.") ;
1022 ActSigIntHandler() ;
1023 if ( what == SIGUSR1 )
1030 MESSAGE("SigIntHandler BEGIN sleeping.") ;
1037 MESSAGE("SigIntHandler LEAVE sleeping after " << count << " s.") ;