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

Luboš Luňák l.lunak at collabora.com
Wed May 30 10:57:59 UTC 2018


 sc/source/core/data/global.cxx |   53 +++++++++++++++++++++++++++++++----------
 1 file changed, 41 insertions(+), 12 deletions(-)

New commits:
commit dfda2730a11e165f081dacbb4b5c30da3db07070
Author: Luboš Luňák <l.lunak at collabora.com>
Date:   Wed May 30 09:00:20 2018 +0200

    protect one-time creation in ScGlobal::Get(Case)Collator() by a mutex
    
    Otherwise there is a race condition when calc uses threading, and lp#390983-2
    sometimes crashes.
    
    Change-Id: I390928c02b8e7d74bebef2dcc98a5c21cb3a8197
    Reviewed-on: https://gerrit.libreoffice.org/54795
    Reviewed-by: Michael Meeks <michael.meeks at collabora.com>
    Tested-by: Luboš Luňák <l.lunak at collabora.com>

diff --git a/sc/source/core/data/global.cxx b/sc/source/core/data/global.cxx
index 9e4ce14e3ddf..4ab08a7bc1bd 100644
--- a/sc/source/core/data/global.cxx
+++ b/sc/source/core/data/global.cxx
@@ -125,6 +125,33 @@ SfxViewShell* pScActiveViewShell = nullptr; //FIXME: Make this a member
 sal_uInt16 nScClickMouseModifier = 0;    //FIXME: This too
 sal_uInt16 nScFillModeMouseModifier = 0; //FIXME: And this
 
+// Thread-safe singleton creation. Ideally rtl_Instance should be used, but that one doesn't
+// allow accessing the pointer (so ScGlobal::Clear() cannot free the objects). So this function
+// is basically rtl_Instance::create() that uses a given pointer.
+template< typename Type, typename Function = std::function< Type*() >,
+          typename Guard = osl::MutexGuard, typename GuardCtor = osl::GetGlobalMutex >
+static inline
+Type* doubleCheckedInit( Type* pointer, Function function, GuardCtor guardCtor = osl::GetGlobalMutex())
+{
+    Type* p = pointer;
+    if (!p)
+    {
+        Guard guard(guardCtor());
+        p = pointer;
+        if (!p)
+        {
+            p = function();
+            OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
+            pointer = p;
+        }
+    }
+    else
+    {
+        OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
+    }
+    return p;
+}
+
 // Static functions
 
 bool ScGlobal::HasAttrChanged( const SfxItemSet&  rNewAttrs,
@@ -996,21 +1023,23 @@ CalendarWrapper*     ScGlobal::GetCalendar()
 }
 CollatorWrapper*        ScGlobal::GetCollator()
 {
-    if ( !pCollator )
-    {
-        pCollator = new CollatorWrapper( ::comphelper::getProcessComponentContext() );
-        pCollator->loadDefaultCollator( *GetLocale(), SC_COLLATOR_IGNORES );
-    }
-    return pCollator;
+    return doubleCheckedInit( pCollator,
+        []()
+        {
+            CollatorWrapper* p = new CollatorWrapper( ::comphelper::getProcessComponentContext() );
+            p->loadDefaultCollator( *GetLocale(), SC_COLLATOR_IGNORES );
+            return p;
+        });
 }
 CollatorWrapper*        ScGlobal::GetCaseCollator()
 {
-    if ( !pCaseCollator )
-    {
-        pCaseCollator = new CollatorWrapper( ::comphelper::getProcessComponentContext() );
-        pCaseCollator->loadDefaultCollator( *GetLocale(), 0 );
-    }
-    return pCaseCollator;
+    return doubleCheckedInit( pCaseCollator,
+        []()
+        {
+            CollatorWrapper* p = new CollatorWrapper( ::comphelper::getProcessComponentContext() );
+            p->loadDefaultCollator( *GetLocale(), 0 );
+            return p;
+        });
 }
 ::utl::TransliterationWrapper* ScGlobal::GetCaseTransliteration()
 {


More information about the Libreoffice-commits mailing list