[Libreoffice-commits] core.git: sc/source

Luboš Luňák l.lunak at collabora.com
Tue Jun 19 14:54:24 UTC 2018


 sc/source/ui/docshell/documentlinkmgr.cxx |   50 +++++++++++++++++-------------
 1 file changed, 29 insertions(+), 21 deletions(-)

New commits:
commit 9b0b29eaa5ca209325a1e8f156d80e676e198c7a
Author: Luboš Luňák <l.lunak at collabora.com>
Date:   Wed Jun 13 18:08:23 2018 +0200

    avoid race condition in DocumentLinkManager::getLinkManager()
    
    Change-Id: Ib8ffcf32e4a4dc80539828611adabb3beef1dafa
    Reviewed-on: https://gerrit.libreoffice.org/55764
    Tested-by: Jenkins
    Reviewed-by: Michael Meeks <michael.meeks at collabora.com>

diff --git a/sc/source/ui/docshell/documentlinkmgr.cxx b/sc/source/ui/docshell/documentlinkmgr.cxx
index c0fcfe0920ab..b1b66a9a8a8d 100644
--- a/sc/source/ui/docshell/documentlinkmgr.cxx
+++ b/sc/source/ui/docshell/documentlinkmgr.cxx
@@ -17,6 +17,7 @@
  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
  */
 
+#include <comphelper/doublecheckedinit.hxx>
 #include <documentlinkmgr.hxx>
 #include <datastream.hxx>
 #include <ddelink.hxx>
@@ -36,7 +37,7 @@ struct DocumentLinkManagerImpl
 {
     SfxObjectShell* mpShell;
     std::unique_ptr<DataStream, o3tl::default_delete<DataStream>> mpDataStream;
-    std::unique_ptr<sfx2::LinkManager> mpLinkManager;
+    std::atomic<sfx2::LinkManager*> mpLinkManager;
 
     DocumentLinkManagerImpl(const DocumentLinkManagerImpl&) = delete;
     const DocumentLinkManagerImpl& operator=(const DocumentLinkManagerImpl&) = delete;
@@ -47,15 +48,17 @@ struct DocumentLinkManagerImpl
     ~DocumentLinkManagerImpl()
     {
         // Shared base links
-        if (mpLinkManager)
+        sfx2::LinkManager* linkManager = mpLinkManager;
+        if (linkManager)
         {
-            sfx2::SvLinkSources aTemp = mpLinkManager->GetServers();
+            sfx2::SvLinkSources aTemp = linkManager->GetServers();
             for (sfx2::SvLinkSources::const_iterator it = aTemp.begin(); it != aTemp.end(); ++it)
                 (*it)->Closed();
 
-            if (!mpLinkManager->GetLinks().empty())
-                mpLinkManager->Remove(0, mpLinkManager->GetLinks().size());
+            if (!linkManager->GetLinks().empty())
+                linkManager->Remove(0, linkManager->GetLinks().size());
         }
+        delete linkManager;
     }
 };
 
@@ -83,23 +86,25 @@ const DataStream* DocumentLinkManager::getDataStream() const
 
 sfx2::LinkManager* DocumentLinkManager::getLinkManager( bool bCreate )
 {
-    if (!mpImpl->mpLinkManager && bCreate && mpImpl->mpShell)
-        mpImpl->mpLinkManager.reset(new sfx2::LinkManager(mpImpl->mpShell));
-    return mpImpl->mpLinkManager.get();
+    if (bCreate && mpImpl->mpShell)
+        return comphelper::doubleCheckedInit( mpImpl->mpLinkManager,
+            [this]() { return new sfx2::LinkManager(mpImpl->mpShell); } );
+    return mpImpl->mpLinkManager;
 }
 
 const sfx2::LinkManager* DocumentLinkManager::getExistingLinkManager() const
 {
-    return mpImpl->mpLinkManager.get();
+    return mpImpl->mpLinkManager;
 }
 
 bool DocumentLinkManager::idleCheckLinks()
 {
-    if (!mpImpl->mpLinkManager)
+    sfx2::LinkManager* pMgr = mpImpl->mpLinkManager;
+    if (!pMgr)
         return false;
 
     bool bAnyLeft = false;
-    const sfx2::SvBaseLinks& rLinks = mpImpl->mpLinkManager->GetLinks();
+    const sfx2::SvBaseLinks& rLinks = pMgr->GetLinks();
     for (const auto & rLink : rLinks)
     {
         sfx2::SvBaseLink* pBase = rLink.get();
@@ -127,10 +132,11 @@ bool DocumentLinkManager::hasDdeOrOleOrWebServiceLinks() const
 
 bool DocumentLinkManager::hasDdeOrOleOrWebServiceLinks(bool bDde, bool bOle, bool bWebService) const
 {
-    if (!mpImpl->mpLinkManager)
+    sfx2::LinkManager* pMgr = mpImpl->mpLinkManager;
+    if (!pMgr)
         return false;
 
-    const sfx2::SvBaseLinks& rLinks = mpImpl->mpLinkManager->GetLinks();
+    const sfx2::SvBaseLinks& rLinks = pMgr->GetLinks();
     for (const auto & rLink : rLinks)
     {
         sfx2::SvBaseLink* pBase = rLink.get();
@@ -147,10 +153,10 @@ bool DocumentLinkManager::hasDdeOrOleOrWebServiceLinks(bool bDde, bool bOle, boo
 
 bool DocumentLinkManager::updateDdeOrOleOrWebServiceLinks(weld::Window* pWin)
 {
-    if (!mpImpl->mpLinkManager)
+    sfx2::LinkManager* pMgr = mpImpl->mpLinkManager;
+    if (!pMgr)
         return false;
 
-    sfx2::LinkManager* pMgr = mpImpl->mpLinkManager.get();
     const sfx2::SvBaseLinks& rLinks = pMgr->GetLinks();
 
     // If the update takes longer, reset all values so that nothing
@@ -210,10 +216,10 @@ bool DocumentLinkManager::updateDdeOrOleOrWebServiceLinks(weld::Window* pWin)
 
 void DocumentLinkManager::updateDdeLink( const OUString& rAppl, const OUString& rTopic, const OUString& rItem )
 {
-    if (!mpImpl->mpLinkManager)
+    sfx2::LinkManager* pMgr = mpImpl->mpLinkManager;
+    if (!pMgr)
         return;
 
-    sfx2::LinkManager* pMgr = mpImpl->mpLinkManager.get();
     const sfx2::SvBaseLinks& rLinks = pMgr->GetLinks();
 
     for (const auto & rLink : rLinks)
@@ -235,11 +241,12 @@ void DocumentLinkManager::updateDdeLink( const OUString& rAppl, const OUString&
 
 size_t DocumentLinkManager::getDdeLinkCount() const
 {
-    if (!mpImpl->mpLinkManager)
+    sfx2::LinkManager* pMgr = mpImpl->mpLinkManager;
+    if (!pMgr)
         return 0;
 
     size_t nDdeCount = 0;
-    const sfx2::SvBaseLinks& rLinks = mpImpl->mpLinkManager->GetLinks();
+    const sfx2::SvBaseLinks& rLinks = pMgr->GetLinks();
     for (const auto & rLink : rLinks)
     {
         ::sfx2::SvBaseLink* pBase = rLink.get();
@@ -255,10 +262,11 @@ size_t DocumentLinkManager::getDdeLinkCount() const
 
 void DocumentLinkManager::disconnectDdeLinks()
 {
-    if (!mpImpl->mpLinkManager)
+    sfx2::LinkManager* pMgr = mpImpl->mpLinkManager;
+    if (!pMgr)
         return;
 
-    const sfx2::SvBaseLinks& rLinks = mpImpl->mpLinkManager->GetLinks();
+    const sfx2::SvBaseLinks& rLinks = pMgr->GetLinks();
     for (const auto & rLink : rLinks)
     {
         ::sfx2::SvBaseLink* pBase = rLink.get();


More information about the Libreoffice-commits mailing list