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

Generated by: LCOV version 1.11