LCOV - code coverage report
Current view: top level - libreoffice/vcl/unx/generic/app - sm.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 320 0.0 %
Date: 2012-12-27 Functions: 0 39 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include "sal/config.h"
      21             : 
      22             : #include <cassert>
      23             : 
      24             : #include <string.h>
      25             : #include <unistd.h>
      26             : #include <sys/poll.h>
      27             : #include <fcntl.h>
      28             : 
      29             : #include <stdio.h>
      30             : 
      31             : #include <rtl/strbuf.hxx>
      32             : 
      33             : #include <rtl/process.h>
      34             : #include <osl/security.h>
      35             : #include <osl/conditn.h>
      36             : 
      37             : #include <tools/prex.h>
      38             : #include <X11/Xatom.h>
      39             : #include <tools/postx.h>
      40             : 
      41             : #include <unx/sm.hxx>
      42             : #include <unx/saldata.hxx>
      43             : #include <unx/saldisp.hxx>
      44             : #include <unx/salframe.h>
      45             : #include <unx/salinst.h>
      46             : 
      47             : #include <vcl/svapp.hxx>
      48             : #include <vcl/window.hxx>
      49             : 
      50             : #include "salsession.hxx"
      51             : 
      52             : namespace {
      53             : 
      54             : class IceSalSession : public SalSession
      55             : {
      56             : public:
      57           0 :     IceSalSession() {}
      58             : 
      59             : private:
      60           0 :     virtual ~IceSalSession() {}
      61             : 
      62             :     virtual void queryInteraction();
      63             :     virtual void interactionDone();
      64             :     virtual void saveDone();
      65             :     virtual bool cancelShutdown();
      66             : };
      67             : 
      68             : }
      69             : 
      70           0 : SalSession* X11SalInstance::CreateSalSession()
      71             : {
      72           0 :     SalSession * p = new IceSalSession;
      73           0 :     SessionManagerClient::open(p);
      74           0 :     return p;
      75             : }
      76             : 
      77           0 : void IceSalSession::queryInteraction()
      78             : {
      79           0 :     if( ! SessionManagerClient::queryInteraction() )
      80             :     {
      81           0 :         SalSessionInteractionEvent aEvent( false );
      82           0 :         CallCallback( &aEvent );
      83             :     }
      84           0 : }
      85             : 
      86           0 : void IceSalSession::interactionDone()
      87             : {
      88           0 :     SessionManagerClient::interactionDone( false );
      89           0 : }
      90             : 
      91           0 : void IceSalSession::saveDone()
      92             : {
      93           0 :     SessionManagerClient::saveDone();
      94           0 : }
      95             : 
      96           0 : bool IceSalSession::cancelShutdown()
      97             : {
      98           0 :     SessionManagerClient::interactionDone( true );
      99           0 :     return false;
     100             : }
     101             : 
     102             : extern "C" void ICEWatchProc(
     103             :     IceConn ice_conn, IcePointer client_data, Bool opening,
     104             :     IcePointer * watch_data);
     105             : 
     106             : extern "C" void SAL_CALL ICEConnectionWorker(void * data);
     107             : 
     108           0 : class ICEConnectionObserver
     109             : {
     110             :     friend void ICEWatchProc(IceConn, IcePointer, Bool, IcePointer *);
     111             : 
     112             :     friend void ICEConnectionWorker(void *);
     113             : 
     114             :     struct pollfd* m_pFilehandles;
     115             :     int m_nConnections;
     116             :     IceConn* m_pConnections;
     117             :     int m_nWakeupFiles[2];
     118             :     oslThread m_ICEThread;
     119             :     IceIOErrorHandler m_origIOErrorHandler;
     120             :     IceErrorHandler m_origErrorHandler;
     121             : 
     122             :     void wakeup();
     123             : 
     124             : public:
     125             :     osl::Mutex m_ICEMutex;
     126             : 
     127           0 :     ICEConnectionObserver():
     128             :         m_pFilehandles(NULL), m_nConnections(0), m_pConnections(NULL),
     129           0 :         m_ICEThread(NULL)
     130           0 :     { m_nWakeupFiles[0] = m_nWakeupFiles[1] = 0; }
     131             : 
     132             :     void activate();
     133             :     void deactivate();
     134             :     void terminate(oslThread iceThread);
     135             : };
     136             : 
     137             : SalSession * SessionManagerClient::m_pSession = NULL;
     138             : boost::scoped_ptr< ICEConnectionObserver >
     139           0 : SessionManagerClient::m_pICEConnectionObserver;
     140             : SmcConn SessionManagerClient::m_pSmcConnection = NULL;
     141           0 : rtl::OString SessionManagerClient::m_aClientID;
     142             : bool SessionManagerClient::m_bDocSaveDone = false; // HACK
     143             : 
     144             : extern "C" {
     145             : 
     146           0 : static void IgnoreIceErrors(
     147             :     SAL_UNUSED_PARAMETER IceConn, SAL_UNUSED_PARAMETER Bool,
     148             :     SAL_UNUSED_PARAMETER int, SAL_UNUSED_PARAMETER unsigned long,
     149             :     SAL_UNUSED_PARAMETER int, SAL_UNUSED_PARAMETER int,
     150             :     SAL_UNUSED_PARAMETER IcePointer)
     151           0 : {}
     152             : 
     153           0 : static void IgnoreIceIOErrors(SAL_UNUSED_PARAMETER IceConn) {}
     154             : 
     155             : }
     156             : 
     157             : static SmProp*  pSmProps = NULL;
     158             : static SmProp** ppSmProps = NULL;
     159             : static int      nSmProps = 0;
     160             : static unsigned char   *pSmRestartHint = NULL;
     161             : 
     162             : 
     163           0 : static void BuildSmPropertyList()
     164             : {
     165           0 :     if( ! pSmProps )
     166             :     {
     167           0 :         rtl::OString aExec(rtl::OUStringToOString(SessionManagerClient::getExecName(), osl_getThreadTextEncoding()));
     168             : 
     169           0 :         nSmProps = 5;
     170           0 :         pSmProps = new SmProp[ nSmProps ];
     171             : 
     172           0 :         pSmProps[ 0 ].name      = const_cast<char*>(SmCloneCommand);
     173           0 :         pSmProps[ 0 ].type      = const_cast<char*>(SmLISTofARRAY8);
     174           0 :         pSmProps[ 0 ].num_vals  = 1;
     175           0 :         pSmProps[ 0 ].vals      = new SmPropValue;
     176           0 :         pSmProps[ 0 ].vals->length  = aExec.getLength()+1;
     177           0 :         pSmProps[ 0 ].vals->value   = strdup( aExec.getStr() );
     178             : 
     179           0 :         pSmProps[ 1 ].name      = const_cast<char*>(SmProgram);
     180           0 :         pSmProps[ 1 ].type      = const_cast<char*>(SmARRAY8);
     181           0 :         pSmProps[ 1 ].num_vals  = 1;
     182           0 :         pSmProps[ 1 ].vals      = new SmPropValue;
     183           0 :         pSmProps[ 1 ].vals->length  = aExec.getLength()+1;
     184           0 :         pSmProps[ 1 ].vals->value   = strdup( aExec.getStr() );
     185             : 
     186           0 :         pSmProps[ 2 ].name      = const_cast<char*>(SmRestartCommand);
     187           0 :         pSmProps[ 2 ].type      = const_cast<char*>(SmLISTofARRAY8);
     188           0 :         pSmProps[ 2 ].num_vals  = 3;
     189           0 :         pSmProps[ 2 ].vals      = new SmPropValue[3];
     190           0 :         pSmProps[ 2 ].vals[0].length    = aExec.getLength()+1;
     191           0 :         pSmProps[ 2 ].vals[0].value = strdup( aExec.getStr() );
     192           0 :         rtl::OStringBuffer aRestartOption;
     193           0 :         aRestartOption.append(RTL_CONSTASCII_STRINGPARAM("--session="));
     194           0 :         aRestartOption.append(SessionManagerClient::getSessionID());
     195           0 :         pSmProps[ 2 ].vals[1].length    = aRestartOption.getLength()+1;
     196           0 :         pSmProps[ 2 ].vals[1].value = strdup(aRestartOption.getStr());
     197           0 :         rtl::OString aRestartOptionNoLogo(RTL_CONSTASCII_STRINGPARAM("--nologo"));
     198           0 :         pSmProps[ 2 ].vals[2].length    = aRestartOptionNoLogo.getLength()+1;
     199           0 :         pSmProps[ 2 ].vals[2].value = strdup(aRestartOptionNoLogo.getStr());
     200             : 
     201           0 :         rtl::OUString aUserName;
     202           0 :         rtl::OString aUser;
     203           0 :         oslSecurity aSec = osl_getCurrentSecurity();
     204           0 :         if( aSec )
     205             :         {
     206           0 :             osl_getUserName( aSec, &aUserName.pData );
     207           0 :             aUser = rtl::OUStringToOString( aUserName, osl_getThreadTextEncoding() );
     208           0 :             osl_freeSecurityHandle( aSec );
     209             :         }
     210             : 
     211           0 :         pSmProps[ 3 ].name      = const_cast<char*>(SmUserID);
     212           0 :         pSmProps[ 3 ].type      = const_cast<char*>(SmARRAY8);
     213           0 :         pSmProps[ 3 ].num_vals  = 1;
     214           0 :         pSmProps[ 3 ].vals      = new SmPropValue;
     215           0 :         pSmProps[ 3 ].vals->value   = strdup( aUser.getStr() );
     216           0 :         pSmProps[ 3 ].vals->length  = rtl_str_getLength( (char *)pSmProps[ 3 ].vals->value )+1;
     217             : 
     218           0 :         pSmProps[ 4 ].name      = const_cast<char*>(SmRestartStyleHint);
     219           0 :         pSmProps[ 4 ].type      = const_cast<char*>(SmCARD8);
     220           0 :         pSmProps[ 4 ].num_vals  = 1;
     221           0 :         pSmProps[ 4 ].vals      = new SmPropValue;
     222           0 :         pSmProps[ 4 ].vals->value   = malloc(1);
     223           0 :         pSmRestartHint = (unsigned char *)pSmProps[ 4 ].vals->value;
     224           0 :         *pSmRestartHint = SmRestartIfRunning;
     225           0 :         pSmProps[ 4 ].vals->length  = 1;
     226             : 
     227           0 :         ppSmProps = new SmProp*[ nSmProps ];
     228           0 :         for( int i = 0; i < nSmProps; i++ )
     229           0 :             ppSmProps[ i ] = &pSmProps[i];
     230             :     }
     231           0 : }
     232             : 
     233           0 : bool SessionManagerClient::checkDocumentsSaved()
     234             : {
     235           0 :     return m_bDocSaveDone;
     236             : }
     237             : 
     238           0 : IMPL_STATIC_LINK_NOINSTANCE( SessionManagerClient, SaveYourselfHdl, void*, pStateVal )
     239             : {
     240             :     // Decode argument smuggled in as void*:
     241           0 :     sal_uIntPtr nStateVal = reinterpret_cast< sal_uIntPtr >(pStateVal);
     242           0 :     Bool shutdown = nStateVal != 0;
     243             : 
     244             :     SAL_INFO("vcl.sm", "posting save documents event shutdown = " << (shutdown ? "true" : "false" ));
     245             : 
     246             :     static bool bFirstShutdown=true;
     247           0 :     if (shutdown && bFirstShutdown) //first shutdown request
     248             :     {
     249           0 :         bFirstShutdown = false;
     250             :         /*
     251             :           If we have no actual frames open, e.g. we launched a quickstarter,
     252             :           and then shutdown all our frames leaving just a quickstarter running,
     253             :           then we don't want to launch an empty toplevel frame on the next
     254             :           start. (The job of scheduling the restart of the quick-starter is a
     255             :           task of the quick-starter)
     256             :         */
     257           0 :         *pSmRestartHint = SmRestartNever;
     258           0 :         const std::list< SalFrame* >& rFrames = GetGenericData()->GetSalDisplay()->getFrames();
     259           0 :         for( std::list< SalFrame* >::const_iterator it = rFrames.begin(); it != rFrames.end(); ++it )
     260             :         {
     261           0 :             Window *pWindow = (*it)->GetWindow();
     262           0 :             if (pWindow && pWindow->IsVisible())
     263             :             {
     264           0 :                 *pSmRestartHint = SmRestartIfRunning;
     265           0 :                 break;
     266             :             }
     267             :         }
     268             :     }
     269             : 
     270           0 :     if( m_pSession )
     271             :     {
     272           0 :         SalSessionSaveRequestEvent aEvent( shutdown, false );
     273           0 :         m_pSession->CallCallback( &aEvent );
     274             :     }
     275             :     else
     276           0 :         saveDone();
     277             : 
     278           0 :     return 0;
     279             : }
     280             : 
     281           0 : IMPL_STATIC_LINK_NOINSTANCE( SessionManagerClient, InteractionHdl, void*, EMPTYARG )
     282             : {
     283             :     SAL_INFO("vcl.sm", "interaction link");
     284           0 :     if( m_pSession )
     285             :     {
     286           0 :         SalSessionInteractionEvent aEvent( true );
     287           0 :         m_pSession->CallCallback( &aEvent );
     288             :     }
     289             : 
     290           0 :     return 0;
     291             : }
     292             : 
     293           0 : IMPL_STATIC_LINK_NOINSTANCE( SessionManagerClient, ShutDownCancelHdl, void*, EMPTYARG )
     294             : {
     295             :     SAL_INFO("vcl.sm", "shutdown cancel");
     296           0 :     if( m_pSession )
     297             :     {
     298           0 :         SalSessionShutdownCancelEvent aEvent;
     299           0 :         m_pSession->CallCallback( &aEvent );
     300             :     }
     301             : 
     302           0 :     return 0;
     303             : }
     304             : 
     305           0 : void SessionManagerClient::SaveYourselfProc(
     306             :     SmcConn,
     307             :     SmPointer,
     308             :     int save_type,
     309             :     Bool shutdown,
     310             :     int interact_style,
     311             :     Bool
     312             :     )
     313             : {
     314             :     SAL_INFO("vcl.sm", "Session: save yourself," <<
     315             :         "save_type " <<
     316             :             " local: " << (save_type == SmSaveLocal) <<
     317             :             " global: " << (save_type == SmSaveGlobal) <<
     318             :             " both: " << (save_type == SmSaveBoth) <<
     319             :         " shutdown: " << shutdown <<
     320             :         " interact_style: " <<
     321             :             " SmInteractStyleNone: " << (interact_style == SmInteractStyleNone) <<
     322             :             " SmInteractStyleErrors: " << (interact_style == SmInteractStyleErrors) <<
     323             :             " SmInteractStyleErrors: " << (interact_style == SmInteractStyleAny));
     324           0 :     BuildSmPropertyList();
     325           0 :     m_bDocSaveDone = false;
     326             :     /* #i49875# some session managers send a "die" message if the
     327             :      * saveDone does not come early enough for their convenience
     328             :      * this can occasionally happen on startup, especially the first
     329             :      * startup. So shortcut the "not shutting down" case since the
     330             :      * upper layers are currently not interested in that event anyway.
     331             :      */
     332           0 :     if( ! shutdown )
     333             :     {
     334           0 :         SessionManagerClient::saveDone();
     335           0 :         return;
     336             :     }
     337             :     // Smuggle argument in as void*:
     338           0 :     sal_uIntPtr nStateVal = shutdown;
     339           0 :     Application::PostUserEvent( STATIC_LINK( 0, SessionManagerClient, SaveYourselfHdl ), reinterpret_cast< void * >(nStateVal) );
     340             :     SAL_INFO("vcl.sm", "waiting for save yourself event to be processed" );
     341             : }
     342             : 
     343           0 : IMPL_STATIC_LINK_NOINSTANCE( SessionManagerClient, ShutDownHdl, void*, EMPTYARG )
     344             : {
     345           0 :     if( m_pSession )
     346             :     {
     347           0 :         SalSessionQuitEvent aEvent;
     348           0 :         m_pSession->CallCallback( &aEvent );
     349             :     }
     350             : 
     351           0 :     const std::list< SalFrame* >& rFrames = GetGenericData()->GetSalDisplay()->getFrames();
     352             :     SAL_INFO("vcl.sm", (rFrames.begin() != rFrames.end() ? "shutdown on first frame" : "shutdown event but no frame"));
     353           0 :     if( rFrames.begin() != rFrames.end() )
     354           0 :         rFrames.front()->CallCallback( SALEVENT_SHUTDOWN, 0 );
     355           0 :     return 0;
     356             : }
     357             : 
     358           0 : void SessionManagerClient::DieProc(
     359             :     SmcConn connection,
     360             :     SmPointer
     361             :     )
     362             : {
     363             :     SAL_INFO("vcl.sm", "Session: die");
     364           0 :     if( connection == m_pSmcConnection )
     365             :     {
     366           0 :         Application::PostUserEvent( STATIC_LINK( NULL, SessionManagerClient, ShutDownHdl ) );
     367             :         SAL_INFO("vcl.sm", "waiting for shutdown event to be processed" );
     368             :     }
     369           0 : }
     370             : 
     371           0 : void SessionManagerClient::SaveCompleteProc(
     372             :     SmcConn,
     373             :     SmPointer
     374             :     )
     375             : {
     376             :     SAL_INFO("vcl.sm", "Session: save complete");
     377           0 : }
     378             : 
     379           0 : void SessionManagerClient::ShutdownCanceledProc(
     380             :     SmcConn connection,
     381             :     SmPointer )
     382             : {
     383             :     SAL_INFO("vcl.sm", "Session: shutdown canceled" );
     384           0 :     if( connection == m_pSmcConnection )
     385           0 :         Application::PostUserEvent( STATIC_LINK( NULL, SessionManagerClient, ShutDownCancelHdl ) );
     386           0 : }
     387             : 
     388           0 : void SessionManagerClient::InteractProc(
     389             :                                         SmcConn connection,
     390             :                                         SmPointer )
     391             : {
     392             :     SAL_INFO("vcl.sm", "Session: interaction request completed" );
     393           0 :     if( connection == m_pSmcConnection )
     394           0 :         Application::PostUserEvent( STATIC_LINK( NULL, SessionManagerClient, InteractionHdl ) );
     395           0 : }
     396             : 
     397           0 : void SessionManagerClient::saveDone()
     398             : {
     399           0 :     if( m_pSmcConnection )
     400             :     {
     401             :         assert(m_pICEConnectionObserver);
     402           0 :         osl::MutexGuard g(m_pICEConnectionObserver->m_ICEMutex);
     403           0 :         SmcSetProperties( m_pSmcConnection, nSmProps, ppSmProps );
     404           0 :         SmcSaveYourselfDone( m_pSmcConnection, True );
     405             :         SAL_INFO("vcl.sm", "sent SaveYourselfDone SmRestartHint of " << *pSmRestartHint );
     406           0 :         m_bDocSaveDone = true;
     407             :     }
     408           0 : }
     409             : 
     410             : 
     411           0 : void SessionManagerClient::open(SalSession * pSession)
     412             : {
     413             :     assert(!m_pSession && !m_pICEConnectionObserver && !m_pSmcConnection);
     414             :         // must only be called once
     415           0 :     m_pSession = pSession;
     416             :     // This is the way Xt does it, so we can too:
     417           0 :     if( getenv( "SESSION_MANAGER" ) )
     418             :     {
     419           0 :         m_pICEConnectionObserver.reset(new ICEConnectionObserver);
     420           0 :         m_pICEConnectionObserver->activate();
     421             : 
     422             :         {
     423           0 :             osl::MutexGuard g(m_pICEConnectionObserver->m_ICEMutex);
     424             : 
     425             :             static SmcCallbacks aCallbacks; // does this need to be static?
     426           0 :             aCallbacks.save_yourself.callback           = SaveYourselfProc;
     427           0 :             aCallbacks.save_yourself.client_data        = NULL;
     428           0 :             aCallbacks.die.callback                     = DieProc;
     429           0 :             aCallbacks.die.client_data                  = NULL;
     430           0 :             aCallbacks.save_complete.callback           = SaveCompleteProc;
     431           0 :             aCallbacks.save_complete.client_data        = NULL;
     432           0 :             aCallbacks.shutdown_cancelled.callback      = ShutdownCanceledProc;
     433           0 :             aCallbacks.shutdown_cancelled.client_data   = NULL;
     434           0 :             rtl::OString aPrevId(getPreviousSessionID());
     435           0 :             char* pClientID = NULL;
     436             :             char aErrBuf[1024];
     437             :             m_pSmcConnection = SmcOpenConnection( NULL,
     438             :                                                   NULL,
     439             :                                                   SmProtoMajor,
     440             :                                                   SmProtoMinor,
     441             :                                                   SmcSaveYourselfProcMask         |
     442             :                                                   SmcDieProcMask                  |
     443             :                                                   SmcSaveCompleteProcMask         |
     444             :                                                   SmcShutdownCancelledProcMask    ,
     445             :                                                   &aCallbacks,
     446           0 :                                                   aPrevId.isEmpty() ? NULL : const_cast<char*>(aPrevId.getStr()),
     447             :                                                   &pClientID,
     448             :                                                   sizeof( aErrBuf ),
     449           0 :                                                   aErrBuf );
     450           0 :             if( !m_pSmcConnection )
     451             :                 SAL_INFO("vcl.sm", "SmcOpenConnection failed: " << aErrBuf);
     452             :             else
     453             :                 SAL_INFO("vcl.sm", "SmcOpenConnection succeeded, client ID is " << pClientID );
     454           0 :             m_aClientID = rtl::OString(pClientID);
     455           0 :             free( pClientID );
     456           0 :             pClientID = NULL;
     457             :         }
     458             : 
     459           0 :         SalDisplay* pDisp = GetGenericData()->GetSalDisplay();
     460           0 :         if( pDisp->GetDrawable(pDisp->GetDefaultXScreen()) && !m_aClientID.isEmpty() )
     461             :         {
     462             :             XChangeProperty( pDisp->GetDisplay(),
     463             :                              pDisp->GetDrawable( pDisp->GetDefaultXScreen() ),
     464             :                              XInternAtom( pDisp->GetDisplay(), "SM_CLIENT_ID", False ),
     465             :                              XA_STRING,
     466             :                              8,
     467             :                              PropModeReplace,
     468           0 :                              (unsigned char*)m_aClientID.getStr(),
     469           0 :                              m_aClientID.getLength()
     470           0 :                              );
     471             :         }
     472             :     }
     473             :     else
     474             :     {
     475             :         SAL_INFO("vcl.sm", "no SESSION_MANAGER");
     476             :     }
     477           0 : }
     478             : 
     479           0 : rtl::OString SessionManagerClient::getSessionID()
     480             : {
     481           0 :     return m_aClientID;
     482             : }
     483             : 
     484           0 : void SessionManagerClient::close()
     485             : {
     486           0 :     if( m_pSmcConnection )
     487             :     {
     488             :         assert(m_pICEConnectionObserver);
     489             :         {
     490           0 :             osl::MutexGuard g(m_pICEConnectionObserver->m_ICEMutex);
     491             :             SAL_INFO("vcl.sm", "attempting SmcCloseConnection");
     492           0 :             SmcCloseConnection( m_pSmcConnection, 0, NULL );
     493           0 :             SAL_INFO("vcl.sm", "SmcConnection closed");
     494             :         }
     495           0 :         m_pICEConnectionObserver->deactivate();
     496           0 :         m_pICEConnectionObserver.reset();
     497           0 :         m_pSmcConnection = NULL;
     498             :     }
     499           0 : }
     500             : 
     501           0 : bool SessionManagerClient::queryInteraction()
     502             : {
     503           0 :     bool bRet = false;
     504           0 :     if( m_pSmcConnection )
     505             :     {
     506             :         assert(m_pICEConnectionObserver);
     507           0 :         osl::MutexGuard g(m_pICEConnectionObserver->m_ICEMutex);
     508           0 :         if( SmcInteractRequest( m_pSmcConnection, SmDialogNormal, InteractProc, NULL ) )
     509           0 :             bRet = true;
     510             :     }
     511           0 :     return bRet;
     512             : }
     513             : 
     514           0 : void SessionManagerClient::interactionDone( bool bCancelShutdown )
     515             : {
     516           0 :     if( m_pSmcConnection )
     517             :     {
     518             :         assert(m_pICEConnectionObserver);
     519           0 :         osl::MutexGuard g(m_pICEConnectionObserver->m_ICEMutex);
     520           0 :         SmcInteractDone( m_pSmcConnection, bCancelShutdown ? True : False );
     521             :     }
     522           0 : }
     523             : 
     524             : 
     525           0 : rtl::OUString SessionManagerClient::getExecName()
     526             : {
     527           0 :     rtl::OUString aExec, aSysExec;
     528           0 :     osl_getExecutableFile( &aExec.pData );
     529           0 :     osl_getSystemPathFromFileURL( aExec.pData, &aSysExec.pData );
     530             : 
     531           0 :     if( aSysExec.endsWith(".bin") )
     532           0 :         aSysExec = aSysExec.copy( 0, aSysExec.getLength() - RTL_CONSTASCII_LENGTH(".bin") );
     533           0 :     return aSysExec;
     534             : }
     535             : 
     536             : 
     537           0 : rtl::OString SessionManagerClient::getPreviousSessionID()
     538             : {
     539           0 :     rtl::OString aPrevId;
     540             : 
     541           0 :     sal_uInt32 n = rtl_getAppCommandArgCount();
     542           0 :     for (sal_uInt32 i = 0; i != n; ++i)
     543             :     {
     544           0 :         ::rtl::OUString aArg;
     545           0 :         rtl_getAppCommandArg( i, &aArg.pData );
     546           0 :         if(aArg.match("--session="))
     547             :         {
     548             :             aPrevId = rtl::OUStringToOString(
     549             :                 aArg.copy(RTL_CONSTASCII_LENGTH("--session=")),
     550           0 :                 osl_getThreadTextEncoding());
     551             :             break;
     552             :         }
     553           0 :     }
     554             : 
     555             :     SAL_INFO("vcl.sm", "previous ID = " << aPrevId.getStr());
     556           0 :     return aPrevId;
     557             : }
     558             : 
     559           0 : void ICEConnectionObserver::activate()
     560             : {
     561             :     /*
     562             :      * Default handlers call exit, we don't care that strongly if something
     563             :      * happens to fail
     564             :      */
     565           0 :     m_origIOErrorHandler = IceSetIOErrorHandler( IgnoreIceIOErrors );
     566           0 :     m_origErrorHandler = IceSetErrorHandler( IgnoreIceErrors );
     567           0 :     IceAddConnectionWatch( ICEWatchProc, this );
     568           0 : }
     569             : 
     570           0 : void ICEConnectionObserver::deactivate()
     571             : {
     572             :     oslThread t;
     573             :     {
     574           0 :         osl::MutexGuard g(m_ICEMutex);
     575           0 :         IceRemoveConnectionWatch( ICEWatchProc, this );
     576           0 :         IceSetErrorHandler( m_origErrorHandler );
     577           0 :         IceSetIOErrorHandler( m_origIOErrorHandler );
     578           0 :         m_nConnections = 0;
     579           0 :         t = m_ICEThread;
     580           0 :         m_ICEThread = NULL;
     581             :     }
     582           0 :     if (t)
     583             :     {
     584           0 :         terminate(t);
     585             :     }
     586           0 : }
     587             : 
     588           0 : void ICEConnectionObserver::wakeup()
     589             : {
     590           0 :     char cChar = 'w';
     591           0 :     OSL_VERIFY(write(m_nWakeupFiles[1], &cChar, 1) == 1);
     592           0 : }
     593             : 
     594           0 : void ICEConnectionObserver::terminate(oslThread iceThread)
     595             : {
     596           0 :     osl_terminateThread(iceThread);
     597           0 :     wakeup();
     598           0 :     osl_joinWithThread(iceThread);
     599           0 :     osl_destroyThread(iceThread);
     600           0 :     close(m_nWakeupFiles[1]);
     601           0 :     close(m_nWakeupFiles[0]);
     602           0 : }
     603             : 
     604           0 : void ICEConnectionWorker(void * data)
     605             : {
     606             :     ICEConnectionObserver * pThis = static_cast< ICEConnectionObserver * >(
     607           0 :         data);
     608           0 :     for (;;)
     609             :     {
     610             :         oslThread t;
     611             :         {
     612           0 :             osl::MutexGuard g(pThis->m_ICEMutex);
     613           0 :             if (pThis->m_ICEThread == NULL || pThis->m_nConnections == 0)
     614             :             {
     615             :                 break;
     616             :             }
     617           0 :             t = pThis->m_ICEThread;
     618             :         }
     619           0 :         if (!osl_scheduleThread(t))
     620             :         {
     621             :             break;
     622             :         }
     623             : 
     624             :         int nConnectionsBefore;
     625             :         struct pollfd* pLocalFD;
     626             :         {
     627           0 :             osl::MutexGuard g(pThis->m_ICEMutex);
     628           0 :             nConnectionsBefore = pThis->m_nConnections;
     629           0 :             int nBytes = sizeof( struct pollfd )*(nConnectionsBefore+1);
     630           0 :             pLocalFD = (struct pollfd*)rtl_allocateMemory( nBytes );
     631           0 :             memcpy( pLocalFD, pThis->m_pFilehandles, nBytes );
     632             :         }
     633             : 
     634           0 :         int nRet = poll( pLocalFD,nConnectionsBefore+1,-1 );
     635           0 :         bool bWakeup = (pLocalFD[0].revents & POLLIN);
     636           0 :         rtl_freeMemory( pLocalFD );
     637             : 
     638           0 :         if( nRet < 1 )
     639           0 :             continue;
     640             : 
     641             :         // clear wakeup pipe
     642           0 :         if( bWakeup )
     643             :         {
     644             :             char buf[4];
     645           0 :             while( read( pThis->m_nWakeupFiles[0], buf, sizeof( buf ) ) > 0 )
     646             :                 ;
     647             :             SAL_INFO("vcl.sm", "file handles active in wakeup: " << nRet);
     648           0 :             if( nRet == 1 )
     649           0 :                 continue;
     650             :         }
     651             : 
     652             :         // check fd's after we obtained the lock
     653           0 :         osl::MutexGuard g(pThis->m_ICEMutex);
     654           0 :         if( pThis->m_nConnections > 0 && pThis->m_nConnections == nConnectionsBefore )
     655             :         {
     656           0 :             nRet = poll( pThis->m_pFilehandles+1, pThis->m_nConnections, 0 );
     657           0 :             if( nRet > 0 )
     658             :             {
     659             :                 SAL_INFO("vcl.sm", "IceProcessMessages");
     660             :                 Bool bReply;
     661           0 :                 for( int i = 0; i < pThis->m_nConnections; i++ )
     662           0 :                     if( pThis->m_pFilehandles[i+1].revents & POLLIN )
     663           0 :                         IceProcessMessages( pThis->m_pConnections[i], NULL, &bReply );
     664             :             }
     665             :         }
     666           0 :     }
     667             :     SAL_INFO("vcl.sm", "shutting down ICE dispatch thread");
     668           0 : }
     669             : 
     670           0 : void ICEWatchProc(
     671             :     IceConn ice_conn, IcePointer client_data, Bool opening,
     672             :     SAL_UNUSED_PARAMETER IcePointer *)
     673             : {
     674             :     // Note: This is a callback function for ICE; this implicitly means that a
     675             :     // call into ICE lib is calling this, so the m_ICEMutex MUST already be
     676             :     // locked by the caller.
     677             :     ICEConnectionObserver * pThis = static_cast< ICEConnectionObserver * >(
     678           0 :         client_data);
     679           0 :     if( opening )
     680             :     {
     681           0 :         int fd = IceConnectionNumber( ice_conn );
     682           0 :         pThis->m_nConnections++;
     683           0 :         pThis->m_pConnections = (IceConn*)rtl_reallocateMemory( pThis->m_pConnections, sizeof( IceConn )*pThis->m_nConnections );
     684           0 :         pThis->m_pFilehandles = (struct pollfd*)rtl_reallocateMemory( pThis->m_pFilehandles, sizeof( struct pollfd )*(pThis->m_nConnections+1) );
     685           0 :         pThis->m_pConnections[ pThis->m_nConnections-1 ]      = ice_conn;
     686           0 :         pThis->m_pFilehandles[ pThis->m_nConnections ].fd     = fd;
     687           0 :         pThis->m_pFilehandles[ pThis->m_nConnections ].events = POLLIN;
     688           0 :         if( pThis->m_nConnections == 1 )
     689             :         {
     690           0 :             if (!pipe(pThis->m_nWakeupFiles))
     691             :             {
     692             :                 int flags;
     693           0 :                 pThis->m_pFilehandles[0].fd      = pThis->m_nWakeupFiles[0];
     694           0 :                 pThis->m_pFilehandles[0].events  = POLLIN;
     695             :                 // set close-on-exec and nonblock descriptor flag.
     696           0 :                 if ((flags = fcntl(pThis->m_nWakeupFiles[0], F_GETFD)) != -1)
     697             :                 {
     698           0 :                     flags |= FD_CLOEXEC;
     699           0 :                     fcntl(pThis->m_nWakeupFiles[0], F_SETFD, flags);
     700             :                 }
     701           0 :                 if ((flags = fcntl(pThis->m_nWakeupFiles[0], F_GETFL)) != -1)
     702             :                 {
     703           0 :                     flags |= O_NONBLOCK;
     704           0 :                     fcntl(pThis->m_nWakeupFiles[0], F_SETFL, flags);
     705             :                 }
     706             :                 // set close-on-exec and nonblock descriptor flag.
     707           0 :                 if ((flags = fcntl(pThis->m_nWakeupFiles[1], F_GETFD)) != -1)
     708             :                 {
     709           0 :                     flags |= FD_CLOEXEC;
     710           0 :                     fcntl(pThis->m_nWakeupFiles[1], F_SETFD, flags);
     711             :                 }
     712           0 :                 if ((flags = fcntl(pThis->m_nWakeupFiles[1], F_GETFL)) != -1)
     713             :                 {
     714           0 :                     flags |= O_NONBLOCK;
     715           0 :                     fcntl(pThis->m_nWakeupFiles[1], F_SETFL, flags);
     716             :                 }
     717             :                 pThis->m_ICEThread = osl_createThread(
     718           0 :                     ICEConnectionWorker, pThis);
     719             :             }
     720             :         }
     721             :     }
     722             :     else // closing
     723             :     {
     724           0 :         for( int i = 0; i < pThis->m_nConnections; i++ )
     725             :         {
     726           0 :             if( pThis->m_pConnections[i] == ice_conn )
     727             :             {
     728           0 :                 if( i < pThis->m_nConnections-1 )
     729             :                 {
     730           0 :                     memmove( pThis->m_pConnections+i, pThis->m_pConnections+i+1, sizeof( IceConn )*(pThis->m_nConnections-i-1) );
     731           0 :                     memmove( pThis->m_pFilehandles+i+1, pThis->m_pFilehandles+i+2, sizeof( struct pollfd )*(pThis->m_nConnections-i-1) );
     732             :                 }
     733           0 :                 pThis->m_nConnections--;
     734           0 :                 pThis->m_pConnections = (IceConn*)rtl_reallocateMemory( pThis->m_pConnections, sizeof( IceConn )*pThis->m_nConnections );
     735           0 :                 pThis->m_pFilehandles = (struct pollfd*)rtl_reallocateMemory( pThis->m_pFilehandles, sizeof( struct pollfd )*(pThis->m_nConnections+1) );
     736           0 :                 break;
     737             :             }
     738             :         }
     739           0 :         if( pThis->m_nConnections == 0 && pThis->m_ICEThread )
     740             :         {
     741             :             SAL_INFO("vcl.sm", "terminating ICEThread");
     742           0 :             oslThread t = pThis->m_ICEThread;
     743           0 :             pThis->m_ICEThread = NULL;
     744             : 
     745             :             // must release the mutex here
     746           0 :             pThis->m_ICEMutex.release();
     747             : 
     748           0 :             pThis->terminate(t);
     749             : 
     750             :             // acquire the mutex again, because the caller does not expect
     751             :             // it to be released when calling into SM
     752           0 :             pThis->m_ICEMutex.acquire();
     753             :         }
     754             :     }
     755             :     SAL_INFO( "vcl.sm", "ICE connection on " << IceConnectionNumber( ice_conn ) << " " << (opening ? "inserted" : "removed"));
     756             :     SAL_INFO( "vcl.sm", "Display connection is " << ConnectionNumber( GetGenericData()->GetSalDisplay()->GetDisplay() ) );
     757           0 : }
     758             : 
     759             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10