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

Generated by: LCOV version 1.10