#89996# close a doc and activate a doc out out win-explorer quickly produces GPF

This commit is contained in:
Carsten Driesner 2001-07-27 10:12:55 +00:00
parent 12b58020db
commit c49f339d07
3 changed files with 292 additions and 82 deletions

View file

@ -2,9 +2,9 @@
*
* $RCSfile: app.cxx,v $
*
* $Revision: 1.30 $
* $Revision: 1.31 $
*
* last change: $Author: cd $ $Date: 2001-07-26 07:45:06 $
* last change: $Author: cd $ $Date: 2001-07-27 11:10:42 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
@ -640,18 +640,22 @@ void Desktop::Main()
// RemoteControl aControl;
InitTestToolLib();
// the shutdown icon sits in the systray and allows the user to keep
// the office instance running for quicker restart
// this will only be activated if -quickstart was specified on cmdline
Reference < XComponent > xQuickstart;
try
{
// the shutdown icon sits in the systray and allows the user to keep
// the office instance running for quicker restart
// this will only be activated if -quickstart was specified on cmdline
RTL_LOGFILE_CONTEXT( aLog, "desktop (cd) createInstance com.sun.star.office.Quickstart" );
sal_Bool bQuickstart = pCmdLineArgs->IsQuickstart();
Sequence< Any > aSeq( 1 );
aSeq[0] <<= bQuickstart;
// Try to instanciate quickstart service. This service is not mandatory, so
// do nothing if service is not available.
RTL_LOGFILE_CONTEXT( aLog, "desktop (cd) createInstance com.sun.star.office.Quickstart" );
xQuickstart = Reference< XComponent >( xSMgr->createInstance( DEFINE_CONST_UNICODE(
"com.sun.star.office.Quickstart" )),
UNO_QUERY );
Reference < XComponent > xQuickstart( xSMgr->createInstanceWithArguments(
DEFINE_CONST_UNICODE( "com.sun.star.office.Quickstart" ), aSeq ),
UNO_QUERY );
}
catch( ::com::sun::star::uno::Exception& )
{
@ -685,6 +689,11 @@ void Desktop::Main()
Reference< XTypeDetection > xTypeDetection( xSMgr->createInstance(
OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.document.TypeDetection" ))),
UNO_QUERY );
Reference< XDesktop > xDesktop( xSMgr->createInstance(
OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.frame.Desktop" ))),
UNO_QUERY );
if ( xDesktop.is() )
xDesktop->addTerminateListener( new OfficeIPCThreadController );
}
// Release solar mutex just before we wait for our client to connect
@ -1044,6 +1053,9 @@ void Desktop::HandleAppEvent( const ApplicationEvent& rAppEvent )
xComp->dispose();
}
}
// remove this pending request
OfficeIPCThread::RequestsCompleted( 1 );
}
else if ( rAppEvent.GetEvent() == "APPEAR" )
{
@ -1075,7 +1087,7 @@ void Desktop::HandleAppEvent( const ApplicationEvent& rAppEvent )
if ( !pCmdLineArgs->IsQuickstart() )
{
// If the office was started the second time its command line arguments are sent through a pipe
// If the office has been started the second time its command line arguments are sent through a pipe
// connection to the first office. We want to reuse the quickstart option for the first office.
// NOTICE: The quickstart service must be initialized inside the "main thread", so we use the
// application events to do this (they are executed inside main thread)!!!

View file

@ -2,9 +2,9 @@
*
* $RCSfile: officeipcthread.cxx,v $
*
* $Revision: 1.3 $
* $Revision: 1.4 $
*
* last change: $Author: cd $ $Date: 2001-07-25 12:10:48 $
* last change: $Author: cd $ $Date: 2001-07-27 11:12:55 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
@ -77,12 +77,20 @@
using namespace vos;
using namespace rtl;
using namespace desktop;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::frame;
#define TERMINATION_SEQUENCE "InternalIPC::TerminateThread"
#define TERMINATION_LENGTH 28
OfficeIPCThread* OfficeIPCThread::pGlobalOfficeIPCThread = 0;
OSecurity OfficeIPCThread::maSecurity;
namespace desktop
{
OfficeIPCThread* OfficeIPCThread::pGlobalOfficeIPCThread = 0;
OSecurity OfficeIPCThread::maSecurity;
::osl::Mutex* OfficeIPCThread::pOfficeIPCThreadMutex = 0;
class ImplForeignAppEventClass
@ -94,6 +102,7 @@ public:
void HandleAppEvent( const ApplicationEvent& rAppEvent );
IMPL_STATIC_LINK( ImplForeignAppEventClass, CallEvent, void*, pEvent )
{
// Application events are processed by the Desktop::HandleAppEvent implementation.
Desktop::HandleAppEvent( *((ApplicationEvent*)pEvent) );
delete (ApplicationEvent*)pEvent;
return 0;
@ -111,8 +120,120 @@ OSignalHandler::TSignalAction SAL_CALL SalMainPipeExchangeSignalHandler::signal(
return (TAction_CallNextHandler);
}
// ----------------------------------------------------------------------------
// The OfficeIPCThreadController implementation is a bookkeeper for all pending requests
// that were created by the OfficeIPCThread. The requests are waiting to be processed by
// our framework loadComponentFromURL function (e.g. open/print request).
// During shutdown the framework is asking OfficeIPCThreadController about pending requests.
// If there are pending requests framework has to stop the shutdown process. It is waiting
// for these requests because framework is not able to handle shutdown and open a document
// concurrently.
// XServiceInfo
OUString SAL_CALL OfficeIPCThreadController::getImplementationName()
throw ( RuntimeException )
{
return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.OfficeIPCThreadController" ));
}
sal_Bool SAL_CALL OfficeIPCThreadController::supportsService( const OUString& ServiceName )
throw ( RuntimeException )
{
return sal_False;
}
Sequence< OUString > SAL_CALL OfficeIPCThreadController::getSupportedServiceNames()
throw ( RuntimeException )
{
Sequence< OUString > aSeq( 0 );
return aSeq;
}
// XEventListener
void SAL_CALL OfficeIPCThreadController::disposing( const EventObject& Source )
throw( RuntimeException )
{
}
// XTerminateListener
void SAL_CALL OfficeIPCThreadController::queryTermination( const EventObject& aEvent )
throw( TerminationVetoException, RuntimeException )
{
// Desktop ask about pending request through our office ipc pipe. We have to
// be sure that no pending request is waiting because framework is not able to
// handle shutdown and open a document concurrently.
if ( OfficeIPCThread::AreRequestsPending() )
throw TerminationVetoException();
else
OfficeIPCThread::BlockAllRequests();
}
void SAL_CALL OfficeIPCThreadController::notifyTermination( const EventObject& aEvent )
throw( RuntimeException )
{
}
// ----------------------------------------------------------------------------
::osl::Mutex& OfficeIPCThread::GetMutex()
{
// Get or create our mutex for thread-saftey
if ( !pOfficeIPCThreadMutex )
{
::osl::MutexGuard aGuard( osl::Mutex::getGlobalMutex() );
if ( !pOfficeIPCThreadMutex )
pOfficeIPCThreadMutex = new osl::Mutex;
}
return *pOfficeIPCThreadMutex;
}
OfficeIPCThread* OfficeIPCThread::GetOfficeIPCThread()
{
// Return the one and only OfficeIPCThread pointer
::osl::MutexGuard aGuard( GetMutex() );
return pGlobalOfficeIPCThread;
}
void OfficeIPCThread::BlockAllRequests()
{
// We have the order to block all incoming requests. Framework
// wants to shutdown and we have to make sure that no loading/printing
// requests are executed anymore.
::osl::MutexGuard aGuard( GetMutex() );
if ( pGlobalOfficeIPCThread )
pGlobalOfficeIPCThread->mbBlockRequests = sal_True;
}
sal_Bool OfficeIPCThread::AreRequestsPending()
{
// Give info about pending requests
::osl::MutexGuard aGuard( GetMutex() );
if ( pGlobalOfficeIPCThread )
return ( pGlobalOfficeIPCThread->mnPendingRequests > 0 );
else
return sal_False;
}
void OfficeIPCThread::RequestsCompleted( int nCount )
{
// Remove nCount pending requests from our internal counter
::osl::MutexGuard aGuard( GetMutex() );
if ( pGlobalOfficeIPCThread )
{
if ( pGlobalOfficeIPCThread->mnPendingRequests > 0 )
pGlobalOfficeIPCThread->mnPendingRequests -= nCount;
}
}
BOOL OfficeIPCThread::EnableOfficeIPCThread()
{
::osl::MutexGuard aGuard( GetMutex() );
if( pGlobalOfficeIPCThread )
return TRUE;
@ -126,6 +247,8 @@ BOOL OfficeIPCThread::EnableOfficeIPCThread()
pThread->maPipeIdent = OUString( RTL_CONSTASCII_USTRINGPARAM( "SingleOfficeIPC_" ) );
// The name of the named pipe is created with the hashcode of the user installation directory (without /user). We have to retrieve
// this information from a unotools implementation.
::utl::BootstrapRetVal aLocateResult = ::utl::bootstrap_locateUserInstallationPath( aOfficeInstallPath, aUserInstallPath, aLastIniFile );
if ( aLocateResult == ::utl::BOOTSTRAP_OK )
{
@ -173,6 +296,8 @@ BOOL OfficeIPCThread::EnableOfficeIPCThread()
void OfficeIPCThread::DisableOfficeIPCThread()
{
::osl::ClearableMutexGuard aGuard( GetMutex() );
if( pGlobalOfficeIPCThread )
{
// send thread a termination message
@ -183,14 +308,18 @@ void OfficeIPCThread::DisableOfficeIPCThread()
Pipe.close();
// close the pipe so that the streampipe on the other
// side produces EOF
aGuard.clear();
// exit gracefully
pGlobalOfficeIPCThread->join();
delete pGlobalOfficeIPCThread;
pGlobalOfficeIPCThread = 0;
}
}
OfficeIPCThread::OfficeIPCThread()
OfficeIPCThread::OfficeIPCThread() :
mbBlockRequests( sal_False ),
mnPendingRequests( 0 )
{
}
@ -207,77 +336,92 @@ void SAL_CALL OfficeIPCThread::run()
{
OPipe::TPipeError
nError = maPipe.accept( maStreamPipe );
if( nError == OStreamPipe::E_None )
{
ByteString aArguments;
char pBuf[ 2049 ];
int nBytes;
do
osl::MutexGuard aMutexGuard( GetMutex() );
if( nError == OStreamPipe::E_None )
{
nBytes = maStreamPipe.read( pBuf, 2048 );
pBuf[ nBytes ] = 0;
aArguments += pBuf;
} while( ! maStreamPipe.isEof() || nBytes > 0 );
maStreamPipe.close();
ByteString aArguments;
char pBuf[ 2049 ];
int nBytes;
do
{
nBytes = maStreamPipe.read( pBuf, 2048 );
pBuf[ nBytes ] = 0;
aArguments += pBuf;
} while( ! maStreamPipe.isEof() || nBytes > 0 );
maStreamPipe.close();
// is this a termination message ? if so, terminate
if( aArguments.CompareTo( TERMINATION_SEQUENCE,
TERMINATION_LENGTH ) == COMPARE_EQUAL )
return;
// is this a termination message ? if so, terminate
if(( aArguments.CompareTo( TERMINATION_SEQUENCE,
TERMINATION_LENGTH ) == COMPARE_EQUAL ) ||
mbBlockRequests )
return;
::rtl::OUString aOpenList;
::rtl::OUString aPrintList;
String aEmpty;
CommandLineArgs aCmdLineArgs( OUString( aArguments.GetBuffer(), aArguments.Len(), gsl_getSystemTextEncoding() ));
::rtl::OUString aOpenList;
::rtl::OUString aPrintList;
String aEmpty;
CommandLineArgs aCmdLineArgs( OUString( aArguments.GetBuffer(), aArguments.Len(), gsl_getSystemTextEncoding() ));
if ( aCmdLineArgs.IsQuickstart() )
{
// we have to use application event, because we have to start quickstart service in main thread!!
ApplicationEvent* pAppEvent =
new ApplicationEvent( aEmpty, aEmpty,
"QUICKSTART", aEmpty );
ImplPostForeignAppEvent( pAppEvent );
if ( aCmdLineArgs.IsQuickstart() )
{
// we have to use application event, because we have to start quickstart service in main thread!!
ApplicationEvent* pAppEvent =
new ApplicationEvent( aEmpty, aEmpty,
"QUICKSTART", aEmpty );
ImplPostForeignAppEvent( pAppEvent );
}
aCmdLineArgs.GetOpenList( aOpenList );
aCmdLineArgs.GetPrintList( aPrintList );
if( aOpenList.getLength() )
{
// open file(s)
ApplicationEvent* pAppEvent =
new ApplicationEvent( aEmpty, aEmpty,
APPEVENT_OPEN_STRING, aOpenList );
ImplPostForeignAppEvent( pAppEvent );
// We are sending a open request to the office. We have to increase our pending request counter!
++mnPendingRequests;
}
if ( aPrintList.getLength() )
{
// print file(s)
ApplicationEvent* pAppEvent =
new ApplicationEvent( aEmpty, aEmpty,
APPEVENT_PRINT_STRING, aPrintList );
ImplPostForeignAppEvent( pAppEvent );
// We are sending a print request to the office. We have to increase our pending request counter!
++mnPendingRequests;
}
if ( aPrintList.getLength() == 0 && aOpenList.getLength() == 0 )
{
// no document was send, just bring Office to front
ApplicationEvent* pAppEvent =
new ApplicationEvent( aEmpty, aEmpty,
"APPEAR", aEmpty );
ImplPostForeignAppEvent( pAppEvent );
}
}
aCmdLineArgs.GetOpenList( aOpenList );
aCmdLineArgs.GetPrintList( aPrintList );
if( aOpenList.getLength() )
else
{
// open file(s)
ApplicationEvent* pAppEvent =
new ApplicationEvent( aEmpty, aEmpty,
APPEVENT_OPEN_STRING, aOpenList );
ImplPostForeignAppEvent( pAppEvent );
}
if ( aPrintList.getLength() )
{
// print file(s)
ApplicationEvent* pAppEvent =
new ApplicationEvent( aEmpty, aEmpty,
APPEVENT_PRINT_STRING, aPrintList );
ImplPostForeignAppEvent( pAppEvent );
}
if ( aPrintList.getLength() == 0 && aOpenList.getLength() == 0 )
{
// no document was send, just bring Office to front
ApplicationEvent* pAppEvent =
new ApplicationEvent( aEmpty, aEmpty,
"APPEAR", aEmpty );
ImplPostForeignAppEvent( pAppEvent );
}
}
else
{
#if defined DEBUG || defined DBG_UTIL
fprintf( stderr, "Error on accept: %d\n", (int)nError );
fprintf( stderr, "Error on accept: %d\n", (int)nError );
#endif
TimeValue tval;
tval.Seconds = 1;
tval.Nanosec = 0;
sleep( tval );
TimeValue tval;
tval.Seconds = 1;
tval.Nanosec = 0;
sleep( tval );
}
}
}
}
}

View file

@ -2,9 +2,9 @@
*
* $RCSfile: officeipcthread.hxx,v $
*
* $Revision: 1.1 $
* $Revision: 1.2 $
*
* last change: $Author: cd $ $Date: 2001-07-16 12:52:33 $
* last change: $Author: cd $ $Date: 2001-07-27 11:12:55 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
@ -62,6 +62,13 @@
#ifndef _DESKTOP_OFFICEIPCTHREAD_HXX_
#define _DESKTOP_OFFICEIPCTHREAD_HXX_
#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
#include <com/sun/star/lang/XServiceInfo.hpp>
#endif
#ifndef _COM_SUN_STAR_FRAME_XTERMINATELISTENER_HPP_
#include <com/sun/star/frame/XTerminateListener.hpp>
#endif
#ifndef _VOS_PIPE_HXX_
#include <vos/pipe.hxx>
#endif
@ -77,6 +84,12 @@
#ifndef _RTL_USTRING_HXX_
#include <rtl/ustring.hxx>
#endif
#ifndef _CPPUHELPER_WEAKBASE2_HXX_
#include <cppuhelper/implbase2.hxx>
#endif
namespace desktop
{
class SalMainPipeExchangeSignalHandler : public vos::OSignalHandler
{
@ -87,11 +100,16 @@ class OfficeIPCThread : public vos::OThread
{
private:
static OfficeIPCThread* pGlobalOfficeIPCThread;
static ::osl::Mutex* pOfficeIPCThreadMutex;
vos::OPipe maPipe;
vos::OStreamPipe maStreamPipe;
static vos::OSecurity maSecurity;
rtl::OUString maPipeIdent;
sal_Bool mbBlockRequests;
int mnPendingRequests;
static ::osl::Mutex& GetMutex();
OfficeIPCThread();
@ -102,9 +120,45 @@ class OfficeIPCThread : public vos::OThread
public:
virtual ~OfficeIPCThread();
// controlling pipe communication during shutdown
static OfficeIPCThread* GetOfficeIPCThread();
static void BlockAllRequests();
static sal_Bool AreRequestsPending();
static void RequestsCompleted( int n = 1 );
// return FALSE if second office
static sal_Bool EnableOfficeIPCThread();
static void DisableOfficeIPCThread();
static sal_Bool EnableOfficeIPCThread();
static void DisableOfficeIPCThread();
};
class OfficeIPCThreadController : public ::cppu::WeakImplHelper2<
::com::sun::star::lang::XServiceInfo,
::com::sun::star::frame::XTerminateListener >
{
public:
OfficeIPCThreadController() {}
virtual ~OfficeIPCThreadController() {}
// XServiceInfo
virtual ::rtl::OUString SAL_CALL getImplementationName()
throw ( ::com::sun::star::uno::RuntimeException );
virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName )
throw ( ::com::sun::star::uno::RuntimeException );
virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames()
throw ( ::com::sun::star::uno::RuntimeException );
// XEventListener
virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source )
throw( ::com::sun::star::uno::RuntimeException );
// XTerminateListener
virtual void SAL_CALL queryTermination( const ::com::sun::star::lang::EventObject& aEvent )
throw( ::com::sun::star::frame::TerminationVetoException, ::com::sun::star::uno::RuntimeException );
virtual void SAL_CALL notifyTermination( const ::com::sun::star::lang::EventObject& aEvent )
throw( ::com::sun::star::uno::RuntimeException );
};
}
#endif // _DESKTOP_OFFICEIPCTHREAD_HXX_