summaryrefslogtreecommitdiff
path: root/desktop
diff options
context:
space:
mode:
authorPierre-Eric Pelloux-Prayer <pierre-eric@lanedo.com>2012-11-20 11:03:03 +0100
committerCaolán McNamara <caolanm@redhat.com>2013-01-28 10:36:39 +0000
commit92e762d0fa56b1c10472f75eec499eabc3ae6ed9 (patch)
treee9203399c3a435db396779a6bfcfe9f0b42ce455 /desktop
parent35cd3d0d6dd6d5d6fc3e406cb452c07cfa7b1a7f (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> (cherry picked from commit 0dce7eae55bf90d2a7171a1fb8663d66ba4ac6d3) (cherry picked from commit 8376da60d5d272cf6b3ebee91934bbcd970c7658) Reviewed-on: https://gerrit.libreoffice.org/1733 Tested-by: Caolán McNamara <caolanm@redhat.com> Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Diffstat (limited to 'desktop')
-rw-r--r--desktop/source/app/officeipcthread.cxx40
-rw-r--r--desktop/source/app/officeipcthread.hxx2
-rw-r--r--desktop/unx/source/start.c17
-rw-r--r--desktop/win32/source/officeloader/officeloader.cxx60
4 files changed, 88 insertions, 31 deletions
diff --git a/desktop/source/app/officeipcthread.cxx b/desktop/source/app/officeipcthread.cxx
index b9ede23532d9..452a3b57910a 100644
--- a/desktop/source/app/officeipcthread.cxx
+++ b/desktop/source/app/officeipcthread.cxx
@@ -66,6 +66,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"; }
@@ -506,8 +508,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
{
@@ -661,6 +686,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 f60a134add53..ba40b576fbbf 100644
--- a/desktop/source/app/officeipcthread.hxx
+++ b/desktop/source/app/officeipcthread.hxx
@@ -103,6 +103,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 c6a8c2b826ed..f7a230650d2f 100644
--- a/desktop/unx/source/start.c
+++ b/desktop/unx/source/start.c
@@ -837,10 +837,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 14c230339121..32ada0b2d997 100644
--- a/desktop/win32/source/officeloader/officeloader.cxx
+++ b/desktop/win32/source/officeloader/officeloader.cxx
@@ -273,42 +273,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;