desktop/inc/dp_misc.h                      |    5 -
 desktop/source/app/officeipcthread.cxx     |   64 ++++-----------
 desktop/source/deployment/misc/dp_misc.cxx |  117 +++++++++++------------------
 3 files changed, 68 insertions(+), 118 deletions(-)

New commits:
commit 522e9816589e0cddcc0ad9f2b83a33f02796ac11
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Wed Jul 23 17:17:43 2025 +0200
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Thu Jul 24 00:15:51 2025 +0200

    Reimplement office_is_running to avoid executable name check
    
    Comparing the executable name is fragile; a different  character case
    could break it.
    
    Create a flag set in PipeIpcThread::execute, which would signal its
    operation. That would reliably resolve i#82778, which was the reason
    for that check.
    
    Change-Id: Ia1baede5f34cd480ce8cfc2d1710d40927af1139
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/188244
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/desktop/inc/dp_misc.h b/desktop/inc/dp_misc.h
index d1a04b21b717..43749711714a 100644
--- a/desktop/inc/dp_misc.h
+++ b/desktop/inc/dp_misc.h
@@ -79,6 +79,8 @@ DESKTOP_DEPLOYMENTMISC_DLLPUBLIC OUString 
makeURLAppendSysPathSegment(
 DESKTOP_DEPLOYMENTMISC_DLLPUBLIC OUString generateRandomPipeId();
 DESKTOP_DEPLOYMENTMISC_DLLPUBLIC OUString generateOfficePipeId();
 
+DESKTOP_DEPLOYMENTMISC_DLLPUBLIC void setOfficeIpcThreadRunning(bool bRunning);
+
 class AbortChannel;
 
 DESKTOP_DEPLOYMENTMISC_DLLPUBLIC
@@ -87,7 +89,7 @@ css::uno::Reference< css::uno::XInterface> resolveUnoURL(
     css::uno::Reference< css::uno::XComponentContext> const & xLocalContext,
     AbortChannel const * abortChannel = nullptr );
 
-
+// Check if office is running on this system (not necessarily in this process!)
 DESKTOP_DEPLOYMENTMISC_DLLPUBLIC bool office_is_running();
 
 
diff --git a/desktop/source/app/officeipcthread.cxx 
b/desktop/source/app/officeipcthread.cxx
index f0a414f984a2..76dbec575e4d 100644
--- a/desktop/source/app/officeipcthread.cxx
+++ b/desktop/source/app/officeipcthread.cxx
@@ -45,6 +45,7 @@
 #include <rtl/process.h>
 #include <o3tl/string_view.hxx>
 #include <comphelper/diagnose_ex.hxx>
+#include <comphelper/scopeguard.hxx>
 
 #include <cassert>
 #include <cstdlib>
@@ -1087,6 +1088,8 @@ bool IpcThread::process(OString const & arguments, bool * 
waitProcessed) {
 void PipeIpcThread::execute()
 {
     assert(m_handler != nullptr);
+    dp_misc::setOfficeIpcThreadRunning(true);
+    comphelper::ScopeGuard resetThreadRunning([]() { 
dp_misc::setOfficeIpcThreadRunning(false); });
     do
     {
         osl::StreamPipe aStreamPipe;
diff --git a/desktop/source/deployment/misc/dp_misc.cxx 
b/desktop/source/deployment/misc/dp_misc.cxx
index 2b083910751e..e0de3cba3f38 100644
--- a/desktop/source/deployment/misc/dp_misc.cxx
+++ b/desktop/source/deployment/misc/dp_misc.cxx
@@ -44,6 +44,7 @@
 #include <com/sun/star/deployment/ExtensionManager.hpp>
 #include <com/sun/star/lang/DisposedException.hpp>
 #include <com/sun/star/task/OfficeRestartManager.hpp>
+#include <atomic>
 #include <memory>
 #include <string_view>
 #include <thread>
@@ -51,11 +52,6 @@
 #include <comphelper/processfactory.hxx>
 #include <salhelper/linkhelper.hxx>
 
-#ifdef _WIN32
-#include <prewin.h>
-#include <postwin.h>
-#endif
-
 using namespace ::com::sun::star;
 using namespace ::com::sun::star::uno;
 
@@ -189,11 +185,10 @@ bool needToSyncRepository(std::u16string_view name)
         folder, file);
 }
 
+// True when IPC thread is running in this process. Set in 
PipeIpcThread::execute. Used to avoid
+// attempts to open the pipe from office_is_running, which could deadlock.
+std::atomic<bool> s_bOfficeIpcThreadRunning = false;
 
-} // anon namespace
-
-
-namespace {
 OUString encodeForRcFile( std::u16string_view str )
 {
     // escape $\{} (=> rtl bootstrap files)
@@ -214,7 +209,7 @@ OUString encodeForRcFile( std::u16string_view str )
     }
     return buf.makeStringAndClear();
 }
-}
+} // anon namespace
 
 
 OUString makeURL( std::u16string_view baseURL, OUString const & relPath_ )
@@ -335,33 +330,13 @@ bool office_is_running()
 #if defined EMSCRIPTEN
     return true;
 #else
-    //We need to check if we run within the office process. Then we must not 
use the pipe, because
-    //this could cause a deadlock. This is actually a workaround for i82778
-    OUString sFile;
-    oslProcessError err = osl_getExecutableFile(& sFile.pData);
-    if (osl_Process_E_None == err)
-    {
-        if (
-#if defined MACOSX
-            sFile.endsWith("/soffice")
-#elif defined UNIX |  defined _WIN32
-            sFile.endsWith("/soffice.bin")
-#else
-#error "Unsupported platform"
-#endif
-
-            )
-            return true;
-    }
-    else
-    {
-        OSL_FAIL("NOT osl_Process_E_None ");
-        //if osl_getExecutableFile failed then we take the risk of creating a 
pipe
-    }
-    return existsOfficePipe();
+    // i#82778: We need to check if we run within the office process. Then we 
must not use the pipe,
+    // because this could cause a deadlock (if called from IPC thread).
+    return s_bOfficeIpcThreadRunning || existsOfficePipe();
 #endif
 }
 
+void setOfficeIpcThreadRunning(bool bRunning) { s_bOfficeIpcThreadRunning = 
bRunning; }
 
 oslProcess raiseProcess(
     OUString const & appURL, Sequence<OUString> const & args )
commit 2b1b4e9f1fb0e24eb4b7d7604154c1c231de0e43
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Wed Jul 23 16:54:41 2025 +0500
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Thu Jul 24 00:15:44 2025 +0200

    Deduplicate code generating IPC pipe id
    
    Make the function in dp_misc available from PipeIpcThread.
    
    Change-Id: I3d4beb3810a270656ea2873545b2c77f6c75486d
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/188228
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/desktop/inc/dp_misc.h b/desktop/inc/dp_misc.h
index f9ac5687e46a..d1a04b21b717 100644
--- a/desktop/inc/dp_misc.h
+++ b/desktop/inc/dp_misc.h
@@ -77,6 +77,7 @@ DESKTOP_DEPLOYMENTMISC_DLLPUBLIC OUString 
makeURLAppendSysPathSegment(
 
 
 DESKTOP_DEPLOYMENTMISC_DLLPUBLIC OUString generateRandomPipeId();
+DESKTOP_DEPLOYMENTMISC_DLLPUBLIC OUString generateOfficePipeId();
 
 class AbortChannel;
 
diff --git a/desktop/source/app/officeipcthread.cxx 
b/desktop/source/app/officeipcthread.cxx
index 6a18a6e6fb48..f0a414f984a2 100644
--- a/desktop/source/app/officeipcthread.cxx
+++ b/desktop/source/app/officeipcthread.cxx
@@ -24,6 +24,7 @@
 #include <config_feature_desktop.h>
 
 #include <app.hxx>
+#include <dp_misc.h>
 #include "officeipcthread.hxx"
 #include "cmdlineargs.hxx"
 #include <com/sun/star/frame/TerminationVetoException.hpp>
@@ -43,6 +44,7 @@
 #include <osl/file.hxx>
 #include <rtl/process.h>
 #include <o3tl/string_view.hxx>
+#include <comphelper/diagnose_ex.hxx>
 
 #include <cassert>
 #include <cstdlib>
@@ -233,36 +235,6 @@ bool addArgument(OStringBuffer &rArguments, char prefix,
 
 rtl::Reference< RequestHandler > RequestHandler::pGlobal;
 
-// Turns a string in aMsg such as file:///home/foo/.libreoffice/3
-// Into a hex string of well known length ff132a86...
-static OUString CreateMD5FromString( const OUString& aMsg )
-{
-    SAL_INFO("desktop.app", "create md5 from '" << aMsg << "'");
-
-    rtlDigest handle = rtl_digest_create( rtl_Digest_AlgorithmMD5 );
-    if ( handle )
-    {
-        const sal_uInt8* pData = reinterpret_cast<const 
sal_uInt8*>(aMsg.getStr());
-        sal_uInt32       nSize = aMsg.getLength() * sizeof( sal_Unicode );
-        sal_uInt32       nMD5KeyLen = rtl_digest_queryLength( handle );
-        std::unique_ptr<sal_uInt8[]> pMD5KeyBuffer(new sal_uInt8[ nMD5KeyLen 
]);
-
-        rtl_digest_init( handle, pData, nSize );
-        rtl_digest_update( handle, pData, nSize );
-        rtl_digest_get( handle, pMD5KeyBuffer.get(), nMD5KeyLen );
-        rtl_digest_destroy( handle );
-
-        // Create hex-value string from the MD5 value to keep the string size 
minimal
-        OUStringBuffer aBuffer( nMD5KeyLen * 2 + 1 );
-        for ( sal_uInt32 i = 0; i < nMD5KeyLen; i++ )
-            aBuffer.append( static_cast<sal_Int32>(pMD5KeyBuffer[i]), 16 );
-
-        return aBuffer.makeStringAndClear();
-    }
-
-    return OUString();
-}
-
 namespace {
 
 class ProcessEventsClass_Impl
@@ -739,26 +711,21 @@ RequestHandler::Status 
PipeIpcThread::enable(rtl::Reference<IpcThread> * thread)
 {
     assert(thread != nullptr);
 
-    // 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.
-    OUString aUserInstallPath;
-    ::utl::Bootstrap::PathStatus aLocateResult = 
::utl::Bootstrap::locateUserInstallation( aUserInstallPath );
-    if (aLocateResult != utl::Bootstrap::PATH_EXISTS
-        && aLocateResult != utl::Bootstrap::PATH_VALID)
-    {
-        return RequestHandler::IPC_STATUS_BOOTSTRAP_ERROR;
-    }
-
     // Try to  determine if we are the first office or not! This should 
prevent multiple
     // access to the user directory !
     // First we try to create our pipe if this fails we try to connect. We 
have to do this
     // in a loop because the other office can crash or shutdown between 
createPipe
     // and connectPipe!!
-    auto aUserInstallPathHashCode = CreateMD5FromString(aUserInstallPath);
-
-    // Check result to create a hash code from the user install path
-    if ( aUserInstallPathHashCode.isEmpty() )
+    OUString aPipeIdent;
+    try
+    {
+        aPipeIdent = dp_misc::generateOfficePipeId();
+    }
+    catch (const Exception&)
+    {
+        DBG_UNHANDLED_EXCEPTION("desktop.app");
         return RequestHandler::IPC_STATUS_BOOTSTRAP_ERROR; // Something 
completely broken, we cannot create a valid hash code!
+    }
 
     osl::Pipe pipe;
     enum PipeMode
@@ -769,7 +736,6 @@ RequestHandler::Status 
PipeIpcThread::enable(rtl::Reference<IpcThread> * thread)
     };
     PipeMode nPipeMode = PIPEMODE_DONTKNOW;
 
-    OUString aPipeIdent( "SingleOfficeIPC_" + aUserInstallPathHashCode );
     do
     {
         osl::Security security;
@@ -825,10 +791,11 @@ RequestHandler::Status 
PipeIpcThread::enable(rtl::Reference<IpcThread> * thread)
             aArguments.append('0');
         }
         sal_uInt32 nCount = rtl_getAppCommandArgCount();
+        OUString arg;
         for( sal_uInt32 i=0; i < nCount; i++ )
         {
-            rtl_getAppCommandArg( i, &aUserInstallPath.pData );
-            if (!addArgument(aArguments, ',', aUserInstallPath)) {
+            rtl_getAppCommandArg(i, &arg.pData);
+            if (!addArgument(aArguments, ',', arg)) {
                 return RequestHandler::IPC_STATUS_BOOTSTRAP_ERROR;
             }
         }
diff --git a/desktop/source/deployment/misc/dp_misc.cxx 
b/desktop/source/deployment/misc/dp_misc.cxx
index 5064aa76e0c9..2b083910751e 100644
--- a/desktop/source/deployment/misc/dp_misc.cxx
+++ b/desktop/source/deployment/misc/dp_misc.cxx
@@ -77,42 +77,6 @@ std::shared_ptr<rtl::Bootstrap> & UnoRc()
 
 #if !defined EMSCRIPTEN
 
-OUString generateOfficePipeId()
-{
-    OUString userPath;
-    ::utl::Bootstrap::PathStatus aLocateResult =
-    ::utl::Bootstrap::locateUserInstallation( userPath );
-    if (aLocateResult != ::utl::Bootstrap::PATH_EXISTS &&
-        aLocateResult != ::utl::Bootstrap::PATH_VALID)
-    {
-        throw Exception(u"Extension Manager: Could not obtain path for 
UserInstallation."_ustr, nullptr);
-    }
-
-    rtlDigest digest = rtl_digest_create( rtl_Digest_AlgorithmMD5 );
-    if (!digest) {
-        throw RuntimeException(u"cannot get digest 
rtl_Digest_AlgorithmMD5!"_ustr, nullptr );
-    }
-
-    sal_uInt8 const * data =
-        reinterpret_cast<sal_uInt8 const *>(userPath.getStr());
-    std::size_t size = userPath.getLength() * sizeof (sal_Unicode);
-    sal_uInt32 md5_key_len = rtl_digest_queryLength( digest );
-    std::unique_ptr<sal_uInt8[]> md5_buf( new sal_uInt8 [ md5_key_len ] );
-
-    rtl_digest_init( digest, data, static_cast<sal_uInt32>(size) );
-    rtl_digest_update( digest, data, static_cast<sal_uInt32>(size) );
-    rtl_digest_get( digest, md5_buf.get(), md5_key_len );
-    rtl_digest_destroy( digest );
-
-    // create hex-value string from the MD5 value to keep
-    // the string size minimal
-    OUStringBuffer buf( "SingleOfficeIPC_" );
-    for ( sal_uInt32 i = 0; i < md5_key_len; ++i ) {
-        buf.append( static_cast<sal_Int32>(md5_buf[ i ]), 0x10 );
-    }
-    return buf.makeStringAndClear();
-}
-
 bool existsOfficePipe()
 {
     static const OUString OfficePipeId = generateOfficePipeId();
@@ -327,6 +291,44 @@ OUString expandUnoRcUrl( OUString const & url )
     }
 }
 
+OUString generateOfficePipeId()
+{
+    // 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.
+
+    OUString userPath;
+    ::utl::Bootstrap::PathStatus aLocateResult =
+    ::utl::Bootstrap::locateUserInstallation( userPath );
+    if (aLocateResult != ::utl::Bootstrap::PATH_EXISTS &&
+        aLocateResult != ::utl::Bootstrap::PATH_VALID)
+    {
+        throw Exception(u"Extension Manager: Could not obtain path for 
UserInstallation."_ustr, nullptr);
+    }
+
+    rtlDigest digest = rtl_digest_create( rtl_Digest_AlgorithmMD5 );
+    if (!digest) {
+        throw RuntimeException(u"cannot get digest 
rtl_Digest_AlgorithmMD5!"_ustr, nullptr );
+    }
+
+    sal_uInt8 const * data =
+        reinterpret_cast<sal_uInt8 const *>(userPath.getStr());
+    std::size_t size = userPath.getLength() * sizeof (sal_Unicode);
+    sal_uInt32 md5_key_len = rtl_digest_queryLength( digest );
+    std::unique_ptr<sal_uInt8[]> md5_buf( new sal_uInt8 [ md5_key_len ] );
+
+    rtl_digest_init( digest, data, static_cast<sal_uInt32>(size) );
+    rtl_digest_update( digest, data, static_cast<sal_uInt32>(size) );
+    rtl_digest_get( digest, md5_buf.get(), md5_key_len );
+    rtl_digest_destroy( digest );
+
+    // create hex-value string from the MD5 value to keep
+    // the string size minimal
+    OUStringBuffer buf( "SingleOfficeIPC_" );
+    for ( sal_uInt32 i = 0; i < md5_key_len; ++i ) {
+        buf.append( static_cast<sal_Int32>(md5_buf[ i ]), 0x10 );
+    }
+    return buf.makeStringAndClear();
+}
 
 bool office_is_running()
 {

Reply via email to