Back to index

salome-gui  6.5.0
Classes | Functions | Variables
SALOME_Session_Server.cxx File Reference
#include <SALOME_NamingService.hxx>
#include <SALOME_ModuleCatalog_impl.hxx>
#include <SALOME_LifeCycleCORBA.hxx>
#include <SALOME_Event.h>
#include <Basics_OCCTVersion.hxx>
#include <Container_init_python.hxx>
#include <ConnectionManager_i.hxx>
#include <RegistryService.hxx>
#include <OpUtil.hxx>
#include <Utils_ORB_INIT.hxx>
#include <Utils_SINGLETON.hxx>
#include <Utils_SALOME_Exception.hxx>
#include <Utils_CorbaException.hxx>
#include <utilities.h>
#include "Session_ServerLauncher.hxx"
#include "Session_ServerCheck.hxx"
#include "Session_Session_i.hxx"
#include <Qtx.h>
#include <QtxSplash.h>
#include <Style_Salome.h>
#include "GUI_version.h"
#include <SUIT_Tools.h>
#include <SUIT_Session.h>
#include <SUIT_Application.h>
#include <SUIT_Desktop.h>
#include <SUIT_ResourceMgr.h>
#include <SUIT_ExceptionHandler.h>
#include <SALOMEconfig.h>
#include <QDir>
#include <QFile>
#include <QApplication>
#include <QMutex>
#include <QWaitCondition>
#include <QRegExp>
#include <QTextStream>

Go to the source code of this file.

Classes

class  SALOME_ResourceMgr
class  SALOME_Session
class  SALOME_QApplication
class  GetInterfaceThread

Functions

void MessageOutput (QtMsgType type, const char *msg)
QString salomeVersion ()
bool isFound (const char *str, int argc, char **argv)
void killOmniNames ()
void shutdownServers (SALOME_NamingService *theNS)
int main (int argc, char **argv)

Variables

PyObject * salome_shared_modules_module = 0
 CORBA server for SALOME Session.
static const char * pixmap_not_found_xpm []

Function Documentation

bool isFound ( const char *  str,
int  argc,
char **  argv 
)

Definition at line 329 of file SALOME_Session_Server.cxx.

{
  for ( int i = 1; i <= ( argc-1 ); i++ )
    if ( !strcmp( argv[i], str ) )
      return true;
  return false;
}

Here is the caller graph for this function:

Definition at line 337 of file SALOME_Session_Server.cxx.

Here is the caller graph for this function:

int main ( int  argc,
char **  argv 
)

Definition at line 350 of file SALOME_Session_Server.cxx.

{
  // Install Qt debug messages handler
  qInstallMsgHandler( MessageOutput );
  
  // add $QTDIR/plugins to the pluins search path for image plugins
  QString qtdir( ::getenv( "QTDIR" ) );
  if ( !qtdir.isEmpty() )
    QApplication::addLibraryPath( QDir( qtdir ).absoluteFilePath( "plugins" ) );

  // Create Qt application instance;
  // this should be done the very first!
  SALOME_QApplication _qappl( argc, argv );
  _qappl.setOrganizationName( "salome" );
  _qappl.setApplicationName( "salome" );
  _qappl.setApplicationVersion( salomeVersion() );

  // Add application library path (to search style plugin etc...)
  QString path = QDir::convertSeparators( SUIT_Tools::addSlash( QString( ::getenv( "GUI_ROOT_DIR" ) ) ) + QString( "bin/salome" ) );
  _qappl.addLibraryPath( path );

  bool isGUI    = isFound( "GUI",    argc, argv );
  bool isSplash = isFound( "SPLASH", argc, argv );
  // Show splash screen (only if both the "GUI" and "SPLASH" parameters are set)
  // Note, that user preferences are not taken into account for splash settings -
  // it is a property of the application!
  QtxSplash* splash = 0;
  if ( isGUI && isSplash ) {
    // ...create resource manager
    SUIT_ResourceMgr resMgr( "SalomeApp", QString( "%1Config" ) );
    resMgr.setCurrentFormat( "xml" );
    resMgr.setWorkingMode( QtxResourceMgr::IgnoreUserValues );
    resMgr.loadLanguage( "LightApp" );
    //
    splash = QtxSplash::splash( QPixmap() );
    splash->readSettings( &resMgr );
    if ( splash->pixmap().isNull() )
      splash->setPixmap( resMgr.loadPixmap( "LightApp", QObject::tr( "ABOUT_SPLASH" ) ) );
    if ( splash->pixmap().isNull() ) {
      delete splash;
      splash = 0;
    }
    else {
      splash->setOption( "%A", QObject::tr( "APP_NAME" ) );
      splash->setOption( "%V", QObject::tr( "ABOUT_VERSION" ).arg( salomeVersion() ) );
      splash->setOption( "%L", QObject::tr( "ABOUT_LICENSE" ) );
      splash->setOption( "%C", QObject::tr( "ABOUT_COPYRIGHT" ) );
      splash->show();
      QApplication::instance()->processEvents();
    }
  }

  
  // Initialization
  int result = -1;

  CORBA::ORB_var orb;
  PortableServer::POA_var poa;

  SUIT_Session* aGUISession = 0;
  SALOME_NamingService* _NS = 0;
  GetInterfaceThread* guiThread = 0;
  Session_ServerLauncher* myServerLauncher = 0;

  try {
    // ...initialize Python (only once)
    int   _argc   = 1;
    char* _argv[] = {(char*)""};
    KERNEL_PYTHON::init_python( _argc,_argv );
    PyEval_RestoreThread( KERNEL_PYTHON::_gtstate );
    if ( !KERNEL_PYTHON::salome_shared_modules_module ) // import only once
      KERNEL_PYTHON::salome_shared_modules_module = PyImport_ImportModule( "salome_shared_modules" );
    if ( !KERNEL_PYTHON::salome_shared_modules_module ) {
      INFOS( "salome_shared_modules_module == NULL" );
      PyErr_Print();
    }
    PyEval_ReleaseThread( KERNEL_PYTHON::_gtstate );

    // ...create ORB, get RootPOA object, NamingService, etc.
    ORB_INIT &init = *SINGLETON_<ORB_INIT>::Instance();
    ASSERT( SINGLETON_<ORB_INIT>::IsAlreadyExisting() );
    int orbArgc = 1;
    orb = init( orbArgc, argv );

    CORBA::Object_var obj = orb->resolve_initial_references( "RootPOA" );
    poa = PortableServer::POA::_narrow( obj );

    PortableServer::POAManager_var pman = poa->the_POAManager();
    pman->activate() ;
    MESSAGE( "pman->activate()" );

    _NS = new SALOME_NamingService( orb );

    result = 0;
  }
  catch ( SALOME_Exception& e ) {
    INFOS( "run(): SALOME::SALOME_Exception is caught: "<<e.what() );
  }
  catch ( CORBA::SystemException& e ) {
    INFOS( "Caught CORBA::SystemException." );
  }
  catch ( CORBA::Exception& e ) {
    INFOS( "Caught CORBA::Exception." );
    CORBA::Any tmp;
    tmp<<= e;
    CORBA::TypeCode_var tc = tmp.type();
    const char *p = tc->name();
    INFOS ( "run(): CORBA exception of the kind : "<<p<< " is caught" );
  }
  catch ( std::exception& e ) {
    INFOS( "run(): An exception has been caught: " <<e.what() );
  }
  catch (...) {
    INFOS( "Caught unknown exception." );
  }

  QMutex _GUIMutex, _SessionMutex, _SplashMutex;
  QWaitCondition _ServerLaunch, _SessionStarted, _SplashStarted;

  // lock session mutex to ensure that GetInterface is not called
  // until all initialization is done
  _SessionMutex.lock();

  if ( !result ) {
    // Start embedded servers launcher (Registry, SALOMEDS, etc.)
    // ...lock mutex to block embedded servers launching thread until wait( mutex )
    _GUIMutex.lock();  
    // ...create launcher
    myServerLauncher = new Session_ServerLauncher( argc, argv, orb, poa, &_GUIMutex, &_ServerLaunch, &_SessionMutex, &_SessionStarted );
    // ...block this thread until launcher is ready
    _ServerLaunch.wait( &_GUIMutex );
    
    // Start servers check thread (splash)
    if ( splash ) {
      // ...lock mutex to block splash thread until wait( mutex )
      _SplashMutex.lock();
      // ...create servers checking thread
      Session_ServerCheck sc( &_SplashMutex, &_SplashStarted );
      // ... set initial progress
      splash->setProgress( 0, sc.totalSteps() );
      // start check loop 
      while ( true ) {
        int step    = sc.currentStep();
        int total   = sc.totalSteps();
        QString msg = sc.currentMessage();
        QString err = sc.error();
        if ( !err.isEmpty() ) {
          QtxSplash::setError( err );
          QApplication::instance()->processEvents();
          result = -1;
          break;
        }
        QtxSplash::setStatus( msg, step );
        QApplication::instance()->processEvents();
        if ( step >= total )
          break;
        // ...block this thread until servers checking is finished
        _SplashStarted.wait( &_SplashMutex );
      }
      // ...unlock mutex 'cause it is no more needed
      _SplashMutex.unlock();
    }

    // Finalize embedded servers launcher 
    // ...block this thread until launcher is finished
    _ServerLaunch.wait( &_GUIMutex );
    // ...unlock mutex 'cause it is no more needed
    _GUIMutex.unlock();
  }

  // Obtain Session interface reference
  CORBA::Object_var obj = _NS->Resolve( "/Kernel/Session" );
  SALOME::Session_var session = SALOME::Session::_narrow( obj ) ;

  bool shutdownAll = false;
  bool shutdownSession = false;
  if ( !result ) {
    // Launch GUI activator
    if ( isGUI ) {
      if ( splash )
        splash->setStatus( QApplication::translate( "", "Activating desktop..." ) );
      // ...create GUI launcher
      MESSAGE( "Session activated, Launch IAPP..." );
      guiThread = new GetInterfaceThread( session );
    }

    // GUI activation
    // Allow multiple activation/deactivation of GUI
    while ( true ) {
      MESSAGE( "waiting wakeAll()" );
      _SessionStarted.wait( &_SessionMutex ); // to be reseased by Launch server thread when ready:
      // atomic operation lock - unlock on mutex
      // unlock mutex: serverThread runs, calls _ServerLaunch->wakeAll()
      // this thread wakes up, and lock mutex

      _SessionMutex.unlock();

      // Session might be shutdowning here, check status
      SALOME::StatSession stat = session->GetStatSession();
      shutdownSession = stat.state == SALOME::shutdown;
      if ( shutdownSession ) {
       _SessionMutex.lock(); // lock mutex before leaving loop - it will be unlocked later
       break;
      }

      // SUIT_Session creation
      aGUISession = new SALOME_Session();

      // Load SalomeApp dynamic library
      MESSAGE( "creation SUIT_Application" );
      SUIT_Application* aGUIApp = aGUISession->startApplication( "SalomeApp", 0, 0 );
      if ( aGUIApp )
      {
        Style_Salome::initialize( aGUIApp->resourceMgr() );
        if ( aGUIApp->resourceMgr()->booleanValue( "Style", "use_salome_style", true ) )
          Style_Salome::apply();

        if ( !isFound( "noexcepthandler", argc, argv ) )
          _qappl.setHandler( aGUISession->handler() ); // after loading SalomeApp application
                                                       // aGUISession contains SalomeApp_ExceptionHandler
        // Run GUI loop
        MESSAGE( "run(): starting the main event loop" );

        if ( splash )
          splash->finish( aGUIApp->desktop() );
       
        result = _qappl.exec();
        
        splash = 0;
       
        if ( result == SUIT_Session::NORMAL ) {
         // desktop is explicitly closed by user from GUI
         // exit flags says if it's necessary to shutdown all servers
         // all session server only
          shutdownAll = aGUISession->exitFlags();
       }
       else {
         // desktop might be closed from:
         // - StopSesion() /temporarily/ or
         // - Shutdown() /permanently/
         stat = session->GetStatSession();
         shutdownSession = stat.state == SALOME::shutdown;
       }
       if ( shutdownAll || shutdownSession ) {
         _SessionMutex.lock(); // lock mutex before leaving loop - it will be unlocked later
         break;
       }
      }

      delete aGUISession;
      aGUISession = 0;
      
      // Prepare _GUIMutex for a new GUI activation
      _SessionMutex.lock();
    }
  }

  // unlock Session mutex
  _SessionMutex.unlock();
  
  if ( shutdownAll )
    shutdownServers( _NS );

  if ( myServerLauncher )
    myServerLauncher->KillAll(); // kill embedded servers

  // Unregister session server
  SALOME_Session_i* sessionServant = dynamic_cast<SALOME_Session_i*>( poa->reference_to_servant( session.in() ) );
  if ( sessionServant )
    sessionServant->NSunregister();

  delete aGUISession;
  delete guiThread;
  delete myServerLauncher;
  delete _NS;

  try  {
    orb->shutdown(0);
  }
  catch (...) {
    // VSR: silently skip exception:
    // CORBA.BAD_INV_ORDER.BAD_INV_ORDER_ORBHasShutdown 
    // exception is raised when orb->destroy() is called and
    // cpp continer is launched in the embedded mode
    // std::cerr << "Caught unexpected exception on shutdown : ignored !!" << std::endl;
    if ( shutdownAll )
      killOmniNames();
    abort(); //abort program to avoid deadlock in destructors or atexit when shutdown has been interrupted
  }

  PyGILState_Ensure();
  //Destroy orb from python (for chasing memory leaks)
  //PyRun_SimpleString("from omniORB import CORBA");
  //PyRun_SimpleString("orb=CORBA.ORB_init([''], CORBA.ORB_ID)");
  //PyRun_SimpleString("orb.destroy()");
  Py_Finalize();

  if ( shutdownAll )
    killOmniNames();

  MESSAGE( "Salome_Session_Server:endofserver" );
  return result;
}

Here is the call graph for this function:

void MessageOutput ( QtMsgType  type,
const char *  msg 
)

Definition at line 99 of file SALOME_Session_Server.cxx.

{
  switch ( type )
  {
  case QtDebugMsg:
    //MESSAGE( "Debug: " << msg );
    break;
  case QtWarningMsg:
    MESSAGE( "Warning: " << msg );
    break;
  case QtFatalMsg:
    MESSAGE( "Fatal: " << msg );
    break;
  }
}

Here is the caller graph for this function:

QString salomeVersion ( )

Definition at line 138 of file SALOME_Session_Server.cxx.

{
  return GUI_VERSION_STR;
}

Here is the caller graph for this function:

void shutdownServers ( SALOME_NamingService *  theNS)

Definition at line 343 of file SALOME_Session_Server.cxx.

{
  SALOME_LifeCycleCORBA lcc(theNS);
  lcc.shutdownServers();
}

Here is the caller graph for this function:


Variable Documentation

const char* pixmap_not_found_xpm[] [static]
Initial value:
 {
"16 16 3 1",
"       c None",
".      c #000000",
"+      c #A80000",
"                ",
"                ",
"    .     .     ",
"   .+.   .+.    ",
"  .+++. .+++.   ",
"   .+++.+++.    ",
"    .+++++.     ",
"     .+++.      ",
"    .+++++.     ",
"   .+++.+++.    ",
"  .+++. .+++.   ",
"   .+.   .+.    ",
"    .     .     ",
"                ",
"                ",
"                "}

Definition at line 116 of file SALOME_Session_Server.cxx.

CORBA server for SALOME Session.

  • read arguments, define list of server to launch with their arguments.
  • wait for naming service
  • create and run a thread for launch of all servers

SALOME_Session Server launches a SALOME session servant. The servant registers to the Naming Service. See SALOME_Session.idl for interface specification.

Main services offered by the servant are:

  • launch GUI
  • stop Session ( must be idle )
  • get session state

Definition at line 97 of file SALOME_Session_Server.cxx.