diff options
author | Pierre-Eric Pelloux-Prayer <pierre-eric@lanedo.com> | 2012-11-20 11:03:03 +0100 |
---|---|---|
committer | Stephan Bergmann <sbergman@redhat.com> | 2012-12-13 11:16:12 +0100 |
commit | 0dce7eae55bf90d2a7171a1fb8663d66ba4ac6d3 (patch) | |
tree | 104a391ba1d2d6cdaa2bc121a522c827e45e8577 | |
parent | 53fbd30b3cd6465251b1b07f4728813d524fcd82 (diff) |
startup: more reliable startup of multiple instances
Until now, when a new soffice instance (S2) started and tried to
connect to an existing soffice process (S1), S2 may have failed to
boostrap due to race condition in communication over the shared pipe.
S1 can be shutdown after S2 connected to it but _before_ S1 handled its
arguments (code run after 'accept' method in OfficeIPCThread).
This patch introduces a new message, sent by the main soffice after it
has called accept if and only if it's not shutting down (see mbDowning
member).
The other soffice waits for this message before enabling going in
PIPE_CONNECTED mode. If soffice fails to receive this message, pipe mode is
left unchanged and after a quick pause, it will try again.
Change-Id: I2e099a5804e1e8dd535cfd31ef454cffa44efa62
Signed-off-by: Stephan Bergmann <sbergman@redhat.com>
-rw-r--r-- | desktop/source/app/officeipcthread.cxx | 40 | ||||
-rw-r--r-- | desktop/source/app/officeipcthread.hxx | 2 | ||||
-rw-r--r-- | desktop/unx/source/start.c | 17 | ||||
-rw-r--r-- | desktop/win32/source/officeloader/officeloader.cxx | 60 |
4 files changed, 88 insertions, 31 deletions
diff --git a/desktop/source/app/officeipcthread.cxx b/desktop/source/app/officeipcthread.cxx index 7047d6976681..7d477a774614 100644 --- a/desktop/source/app/officeipcthread.cxx +++ b/desktop/source/app/officeipcthread.cxx @@ -57,6 +57,8 @@ const char *OfficeIPCThread::sc_aShowSequence = "-tofront"; const int OfficeIPCThread::sc_nShSeqLength = 5; const char *OfficeIPCThread::sc_aConfirmationSequence = "InternalIPC::ProcessingDone"; const int OfficeIPCThread::sc_nCSeqLength = 27; +const char *OfficeIPCThread::sc_aSendArgumentsSequence = "InternalIPC::SendArguments"; +const int OfficeIPCThread::sc_nCSASeqLength = 26; namespace { static char const ARGUMENT_PREFIX[] = "InternalIPC::Arguments"; } @@ -497,8 +499,31 @@ OfficeIPCThread::Status OfficeIPCThread::EnableOfficeIPCThread() } else if( pThread->maPipe.create( pThread->maPipeIdent.getStr(), osl_Pipe_OPEN, rSecurity )) // Creation not successfull, now we try to connect { - // Pipe connected to first office - nPipeMode = PIPEMODE_CONNECTED; + osl::StreamPipe aStreamPipe(pThread->maPipe.getHandle()); + char pReceiveBuffer[sc_nCSASeqLength + 1]; + int nResult = 0; + int nBytes = 0; + int nBufSz = sc_nCSASeqLength + 1; + // read byte per byte + while ((nResult=aStreamPipe.recv( pReceiveBuffer+nBytes, nBufSz-nBytes))>0) { + nBytes += nResult; + if (pReceiveBuffer[nBytes-1]=='\0') { + break; + } + } + if (rtl::OString(sc_aSendArgumentsSequence).equals(pReceiveBuffer)) + { + // Pipe connected to first office + nPipeMode = PIPEMODE_CONNECTED; + } + else + { + // Pipe connection failed (other office exited or crashed) + TimeValue tval; + tval.Seconds = 0; + tval.Nanosec = 500000000; + salhelper::Thread::wait( tval ); + } } else { @@ -655,6 +680,17 @@ void OfficeIPCThread::execute() // down during wait osl::ClearableMutexGuard aGuard( GetMutex() ); + if (!mbDowning) + { + // notify client we're ready to process its args + int nBytes = 0; + int nResult = 0; + while ( + (nResult = maStreamPipe.send(sc_aSendArgumentsSequence+nBytes, sc_nCSASeqLength-nBytes))>0 && + ((nBytes += nResult) < sc_nCSASeqLength) ) ; + } + maStreamPipe.write("\0", 1); + // test byte by byte const int nBufSz = 2048; char pBuf[nBufSz]; diff --git a/desktop/source/app/officeipcthread.hxx b/desktop/source/app/officeipcthread.hxx index 734119d61ad9..3dd7eac5197c 100644 --- a/desktop/source/app/officeipcthread.hxx +++ b/desktop/source/app/officeipcthread.hxx @@ -94,6 +94,8 @@ class OfficeIPCThread : public salhelper::Thread static const int sc_nShSeqLength; static const char *sc_aConfirmationSequence; static const int sc_nCSeqLength; + static const char *sc_aSendArgumentsSequence; + static const int sc_nCSASeqLength; OfficeIPCThread(); diff --git a/desktop/unx/source/start.c b/desktop/unx/source/start.c index 2d12d89e89cc..0e32c590f9de 100644 --- a/desktop/unx/source/start.c +++ b/desktop/unx/source/start.c @@ -839,10 +839,19 @@ SAL_IMPLEMENT_MAIN_WITH_ARGS( argc, argv ) if ( ( fd = connect_pipe( pPipePath ) ) >= 0 ) { - rtl_uString *pCwdPath = NULL; - osl_getProcessWorkingDir( &pCwdPath ); - - bSentArgs = send_args( fd, pCwdPath ); + // Wait for answer + char resp[ strlen( "InternalIPC::SendArguments" ) + 1]; + ssize_t n = read( fd, resp, SAL_N_ELEMENTS( resp ) ); + if (n == (ssize_t) SAL_N_ELEMENTS( resp ) + && (memcmp( + resp, "InternalIPC::SendArguments", + SAL_N_ELEMENTS( resp ) - 1) == 0)) { + rtl_uString *pCwdPath = NULL; + osl_getProcessWorkingDir( &pCwdPath ); + + // Then send args + bSentArgs = send_args( fd, pCwdPath ); + } close( fd ); } diff --git a/desktop/win32/source/officeloader/officeloader.cxx b/desktop/win32/source/officeloader/officeloader.cxx index b1a42565d547..c7c91c64f707 100644 --- a/desktop/win32/source/officeloader/officeloader.cxx +++ b/desktop/win32/source/officeloader/officeloader.cxx @@ -264,42 +264,52 @@ int WINAPI _tWinMain( HINSTANCE, HINSTANCE, LPTSTR, int ) if ( INVALID_HANDLE_VALUE != hPipe ) { - DWORD dwBytesWritten; - int argc2 = 0; - LPWSTR *argv2 = CommandLineToArgvW( GetCommandLine(), &argc2 ); - - fSuccess = WriteFile( hPipe, RTL_CONSTASCII_STRINGPARAM("InternalIPC::Arguments"), &dwBytesWritten, NULL ); - if (fSuccess) { - if (cwdLen > 0) { - fSuccess = writeArgument(hPipe, '2', cwd); - } else { - fSuccess = WriteFile( - hPipe, RTL_CONSTASCII_STRINGPARAM("0"), - &dwBytesWritten, NULL); - } - } - for ( int argn = 1; fSuccess && argn < argc2; argn++ ) + DWORD dwBytesRead = 0; + char *pBuffer = (char *)_alloca( sizeof("InternalIPC::SendArguments") + 1); + fSuccess = ReadFile( hPipe, pBuffer, sizeof("InternalIPC::SendArguments") + 1, &dwBytesRead, NULL ); + if ( fSuccess ) { - fSuccess = writeArgument(hPipe, ',', argv2[argn]); + fSuccess = (dwBytesRead == (sizeof("InternalIPC::SendArguments") + 1) && + 0 == strncmp( "InternalIPC::SendArguments", pBuffer, dwBytesRead - 1 ) ); } - if ( fSuccess ) { - fSuccess = WriteFile( hPipe, "", 1, &dwBytesWritten, NULL ); + DWORD dwBytesWritten; + int argc2 = 0; + LPWSTR *argv2 = CommandLineToArgvW( GetCommandLine(), &argc2 ); + + fSuccess = WriteFile( hPipe, RTL_CONSTASCII_STRINGPARAM("InternalIPC::Arguments"), &dwBytesWritten, NULL ); + if (fSuccess) { + if (cwdLen > 0) { + fSuccess = writeArgument(hPipe, '2', cwd); + } else { + fSuccess = WriteFile( + hPipe, RTL_CONSTASCII_STRINGPARAM("0"), + &dwBytesWritten, NULL); + } + } + for ( int argn = 1; fSuccess && argn < argc2; argn++ ) + { + fSuccess = writeArgument(hPipe, ',', argv2[argn]); + } + if ( fSuccess ) { - DWORD dwBytesRead = 0; - char *pBuffer = (char *)_alloca( sizeof(PIPE_TERMINATION_SEQUENCE) ); - fSuccess = ReadFile( hPipe, pBuffer, sizeof(PIPE_TERMINATION_SEQUENCE) - 1, &dwBytesRead, NULL ); + fSuccess = WriteFile( hPipe, "", 1, &dwBytesWritten, NULL ); if ( fSuccess ) { - pBuffer[dwBytesRead] = 0; - if ( 0 != strcmp( PIPE_TERMINATION_SEQUENCE, pBuffer ) ) - fSuccess = FALSE; + DWORD dwBytesRead = 0; + char *pBuffer = (char *)_alloca( sizeof(PIPE_TERMINATION_SEQUENCE) ); + fSuccess = ReadFile( hPipe, pBuffer, sizeof(PIPE_TERMINATION_SEQUENCE) - 1, &dwBytesRead, NULL ); + if ( fSuccess ) + { + pBuffer[dwBytesRead] = 0; + if ( 0 != strcmp( PIPE_TERMINATION_SEQUENCE, pBuffer ) ) + fSuccess = FALSE; + } } } } - CloseHandle( hPipe ); return fSuccess ? 0 : -1; |