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

Stephan Bergmann (via logerrit) logerrit at kemper.freedesktop.org
Mon Aug 2 15:10:24 UTC 2021


 i18nlangtag/source/languagetag/languagetag.cxx |   89 +++++++++++++------------
 1 file changed, 48 insertions(+), 41 deletions(-)

New commits:
commit 71d0c43fb4cf535239cb41baf7b6e03de765ce7a
Author:     Stephan Bergmann <sbergman at redhat.com>
AuthorDate: Mon Aug 2 15:41:53 2021 +0200
Commit:     Stephan Bergmann <sbergman at redhat.com>
CommitDate: Mon Aug 2 17:09:49 2021 +0200

    initialization-order-fiasco
    
    ...after a943936eeff04b60ebd0b2552bc18b42606f3321 "rtl::Static -> static local"
    (and the relevant static isn't even local), when building e.g.
    Gallery/backgrounds, see <https://ci.libreoffice.org/job/lo_ubsan/2090/>:
    
    > ==26993==ERROR: AddressSanitizer: initialization-order-fiasco on address 0x2b52e50be408 at pc 0x2b52e4d32753 bp 0x7fff5670f090 sp 0x7fff5670f088
    > READ of size 8 at 0x2b52e50be408 thread T0
    >     #0 0x2b52e4d32752 in std::_Rb_tree<rtl::OUString, std::pair<rtl::OUString const, std::shared_ptr<LanguageTagImpl> >, std::_Select1st<std::pair<rtl::OUString const, std::shared_ptr<LanguageTagImpl> > >, (anonymous namespace)::compareIgnoreAsciiCaseLess, std::allocator<std::pair<rtl::OUString const, std::shared_ptr<LanguageTagImpl> > > >::_M_begin() /home/tdf/lode/opt_private/gcc-7.3.0/lib/gcc/x86_64-pc-linux-gnu/7.3.0/../../../../include/c++/7.3.0/bits/stl_tree.h:737:64
    >     #1 0x2b52e4d355f3 in std::_Rb_tree<rtl::OUString, std::pair<rtl::OUString const, std::shared_ptr<LanguageTagImpl> >, std::_Select1st<std::pair<rtl::OUString const, std::shared_ptr<LanguageTagImpl> > >, (anonymous namespace)::compareIgnoreAsciiCaseLess, std::allocator<std::pair<rtl::OUString const, std::shared_ptr<LanguageTagImpl> > > >::find(rtl::OUString const&) /home/tdf/lode/opt_private/gcc-7.3.0/lib/gcc/x86_64-pc-linux-gnu/7.3.0/../../../../include/c++/7.3.0/bits/stl_tree.h:2523:37
    >     #2 0x2b52e4d3507d in std::__cxx1998::map<rtl::OUString, std::shared_ptr<LanguageTagImpl>, (anonymous namespace)::compareIgnoreAsciiCaseLess, std::allocator<std::pair<rtl::OUString const, std::shared_ptr<LanguageTagImpl> > > >::find(rtl::OUString const&) /home/tdf/lode/opt_private/gcc-7.3.0/lib/gcc/x86_64-pc-linux-gnu/7.3.0/../../../../include/c++/7.3.0/bits/stl_map.h:1164:21
    >     #3 0x2b52e4cf116c in std::__debug::map<rtl::OUString, std::shared_ptr<LanguageTagImpl>, (anonymous namespace)::compareIgnoreAsciiCaseLess, std::allocator<std::pair<rtl::OUString const, std::shared_ptr<LanguageTagImpl> > > >::find(rtl::OUString const&) /home/tdf/lode/opt_private/gcc-7.3.0/lib/gcc/x86_64-pc-linux-gnu/7.3.0/../../../../include/c++/7.3.0/debug/map.h:561:32
    >     #4 0x2b52e4d00dcd in LanguageTag::registerImpl() const /i18nlangtag/source/languagetag/languagetag.cxx:888:50
    >     #5 0x2b52e4cdf693 in LanguageTag::getImpl() /i18nlangtag/source/languagetag/languagetag.cxx:1004:18
    >     #6 0x2b52e4cdf3fd in LanguageTag::LanguageTag(rtl::OUString const&, bool) /i18nlangtag/source/languagetag/languagetag.cxx:489:9
    >     #7 0x2b52b9aed628 in __cxx_global_var_init.2 /sfx2/source/view/lokhelper.cxx:77:13
    >     #8 0x2b52b9aed75e in _GLOBAL__sub_I_lokhelper.cxx /sfx2/source/view/lokhelper.cxx
    >     #9 0x2b52b4f069c2 in _dl_init_internal (/lib64/ld-linux-x86-64.so.2+0xf9c2)
    >     #10 0x2b52b4ef8179  (/lib64/ld-linux-x86-64.so.2+0x1179)
    >
    > 0x2b52e50be408 is located 40 bytes inside of global variable '(anonymous namespace)::theMapBcp47' defined in '/home/tdf/lode/jenkins/workspace/lo_ubsan/i18nlangtag/source/languagetag/languagetag.cxx:93:10' (0x2b52e50be3e0) of size 72
    >   registered at:
    >     #0 0x43f4c8 in __asan_register_globals.part.13 /home/tdf/lode/packages/llvm-llvmorg-9.0.1.src/compiler-rt/lib/asan/asan_globals.cc:362
    >     #1 0x2b52e4d4031b in asan.module_ctor (/instdir/program/libi18nlangtag.so+0x16831b)
    > LLVMSymbolizer: error reading file: No such file or directory
    >     #2 0x7fff567143b7  ([stack]+0x203b7)
    
    This is a partial revert of a943936eeff04b60ebd0b2552bc18b42606f3321
    "rtl::Static -> static local".
    
    Change-Id: I5d6803d217d4e8927b5864b2392f3ddd18310a5a
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/119882
    Tested-by: Jenkins
    Reviewed-by: Stephan Bergmann <sbergman at redhat.com>

diff --git a/i18nlangtag/source/languagetag/languagetag.cxx b/i18nlangtag/source/languagetag/languagetag.cxx
index 07b9c6d0a666..41f23973020f 100644
--- a/i18nlangtag/source/languagetag/languagetag.cxx
+++ b/i18nlangtag/source/languagetag/languagetag.cxx
@@ -49,19 +49,24 @@ struct myLtError
     ~myLtError() { if (p) lt_error_unref( p); }
 };
 
+// "static" to be returned as const reference to an empty locale.
+struct theEmptyLocale : public rtl::Static< lang::Locale, theEmptyLocale > {};
 }
 
 typedef std::unordered_set< OUString > KnownTagSet;
 namespace {
+struct theKnowns : public rtl::Static< KnownTagSet, theKnowns > {};
 struct theMutex : public rtl::Static< osl::Mutex, theMutex > {};
 }
 
 static const KnownTagSet & getKnowns()
 {
-    static const KnownTagSet theKnowns =
-        []()
+    KnownTagSet & rKnowns = theKnowns::get();
+    if (rKnowns.empty())
+    {
+        osl::MutexGuard aGuard( theMutex::get());
+        if (rKnowns.empty())
         {
-            KnownTagSet knownSet;
             ::std::vector< MsLangId::LanguagetagMapping > aDefined( MsLangId::getDefinedLanguagetags());
             for (auto const& elemDefined : aDefined)
             {
@@ -71,12 +76,12 @@ static const KnownTagSet & getKnowns()
                 ::std::vector< OUString > aFallbacks( LanguageTag( elemDefined.mnLang).getFallbackStrings( true));
                 for (auto const& fallback : aFallbacks)
                 {
-                    knownSet.insert(fallback);
+                    rKnowns.insert(fallback);
                 }
             }
-            return knownSet;
-        }();
-    return theKnowns;
+        }
+    }
+    return rKnowns;
 }
 
 
@@ -90,10 +95,10 @@ struct compareIgnoreAsciiCaseLess
 };
 typedef ::std::map< OUString, LanguageTag::ImplPtr, compareIgnoreAsciiCaseLess > MapBcp47;
 typedef ::std::map< LanguageType, LanguageTag::ImplPtr > MapLangID;
-MapBcp47 theMapBcp47;
-MapLangID theMapLangID;
-LanguageTag::ImplPtr theDontKnow;
-LanguageTag::ImplPtr theSystemLocale;
+struct theMapBcp47 : public rtl::Static< MapBcp47, theMapBcp47 > {};
+struct theMapLangID : public rtl::Static< MapLangID, theMapLangID > {};
+struct theDontKnow : public rtl::Static< LanguageTag::ImplPtr, theDontKnow > {};
+struct theSystemLocale : public rtl::Static< LanguageTag::ImplPtr, theSystemLocale > {};
 }
 
 
@@ -593,9 +598,10 @@ LanguageTag::ImplPtr LanguageTagImpl::registerOnTheFly( LanguageType nRegisterID
 
     osl::MutexGuard aGuard( theMutex::get());
 
-    MapBcp47::const_iterator it( theMapBcp47.find( maBcp47));
+    MapBcp47& rMapBcp47 = theMapBcp47::get();
+    MapBcp47::const_iterator it( rMapBcp47.find( maBcp47));
     bool bOtherImpl = false;
-    if (it != theMapBcp47.end())
+    if (it != rMapBcp47.end())
     {
         SAL_INFO( "i18nlangtag", "LanguageTag::registerOnTheFly: found impl for '" << maBcp47 << "'");
         pImpl = (*it).second;
@@ -615,7 +621,7 @@ LanguageTag::ImplPtr LanguageTagImpl::registerOnTheFly( LanguageType nRegisterID
     {
         SAL_INFO( "i18nlangtag", "LanguageTag::registerOnTheFly: new impl for '" << maBcp47 << "'");
         pImpl = std::make_shared<LanguageTagImpl>( *this);
-        theMapBcp47.insert( ::std::make_pair( maBcp47, pImpl));
+        rMapBcp47.insert( ::std::make_pair( maBcp47, pImpl));
     }
 
     if (!bOtherImpl || !pImpl->mbInitializedLangID)
@@ -628,8 +634,9 @@ LanguageTag::ImplPtr LanguageTagImpl::registerOnTheFly( LanguageType nRegisterID
             // different, otherwise we would end up with ambiguous assignments
             // of different language tags, for example for the same primary
             // LangID with "no", "nb" and "nn".
-            MapLangID::const_iterator itID( theMapLangID.find( nRegisterID));
-            if (itID != theMapLangID.end())
+            const MapLangID& rMapLangID = theMapLangID::get();
+            MapLangID::const_iterator itID( rMapLangID.find( nRegisterID));
+            if (itID != rMapLangID.end())
             {
                 if ((*itID).second->maBcp47 != maBcp47)
                 {
@@ -660,7 +667,7 @@ LanguageTag::ImplPtr LanguageTagImpl::registerOnTheFly( LanguageType nRegisterID
     }
 
     ::std::pair< MapLangID::const_iterator, bool > res(
-            theMapLangID.insert( ::std::make_pair( pImpl->mnLangID, pImpl)));
+            theMapLangID::get().insert( ::std::make_pair( pImpl->mnLangID, pImpl)));
     if (res.second)
     {
         SAL_INFO( "i18nlangtag", "LanguageTag::registerOnTheFly: cross-inserted 0x"
@@ -679,8 +686,9 @@ LanguageTag::ImplPtr LanguageTagImpl::registerOnTheFly( LanguageType nRegisterID
 
 LanguageTag::ScriptType LanguageTag::getOnTheFlyScriptType( LanguageType nRegisterID )
 {
-    MapLangID::const_iterator itID( theMapLangID.find( nRegisterID));
-    if (itID != theMapLangID.end())
+    const MapLangID& rMapLangID = theMapLangID::get();
+    MapLangID::const_iterator itID( rMapLangID.find( nRegisterID));
+    if (itID != rMapLangID.end())
         return (*itID).second->getScriptType();
     else
         return ScriptType::UNKNOWN;
@@ -701,7 +709,7 @@ void LanguageTag::setConfiguredSystemLanguage( LanguageType nLang )
     MsLangId::LanguageTagAccess::setConfiguredSystemLanguage( nLang);
     // Reset system locale to none and let registerImpl() do the rest to
     // initialize a new one.
-    theSystemLocale.reset();
+    theSystemLocale::get().reset();
     LanguageTag aLanguageTag( LANGUAGE_SYSTEM);
     aLanguageTag.registerImpl();
 }
@@ -741,7 +749,7 @@ LanguageTag::ImplPtr LanguageTag::registerImpl() const
     // and take the system locale shortcut if possible.
     if (mbSystemLocale)
     {
-        pImpl = theSystemLocale;
+        pImpl = theSystemLocale::get();
         if (pImpl)
         {
 #if OSL_DEBUG_LEVEL > 0
@@ -766,9 +774,10 @@ LanguageTag::ImplPtr LanguageTag::registerImpl() const
             // Heavy usage of LANGUAGE_DONTKNOW, make it an own Impl for all the
             // conversion attempts. At the same time provide a central breakpoint
             // to inspect such places.
-            if (!theDontKnow)
-                theDontKnow = std::make_shared<LanguageTagImpl>( *this);
-            pImpl = theDontKnow;
+            LanguageTag::ImplPtr& rDontKnow = theDontKnow::get();
+            if (!rDontKnow)
+                rDontKnow = std::make_shared<LanguageTagImpl>( *this);
+            pImpl = rDontKnow;
 #if OSL_DEBUG_LEVEL > 0
             static size_t nCallsDontKnow = 0;
             ++nCallsDontKnow;
@@ -779,7 +788,7 @@ LanguageTag::ImplPtr LanguageTag::registerImpl() const
         else
         {
             // A great share are calls for a system equal locale.
-            pImpl = theSystemLocale;
+            pImpl = theSystemLocale::get();
             if (pImpl && pImpl->mnLangID == mnLangID)
             {
 #if OSL_DEBUG_LEVEL > 0
@@ -810,7 +819,7 @@ LanguageTag::ImplPtr LanguageTag::registerImpl() const
     if (mbInitializedBcp47)
     {
         // A great share are calls for a system equal locale.
-        pImpl = theSystemLocale;
+        pImpl = theSystemLocale::get();
         if (pImpl && pImpl->maBcp47 == maBcp47)
         {
 #if OSL_DEBUG_LEVEL > 0
@@ -843,8 +852,9 @@ LanguageTag::ImplPtr LanguageTag::registerImpl() const
     // Prefer LangID map as find+insert needs less comparison work.
     if (mbInitializedLangID)
     {
-        MapLangID::const_iterator it( theMapLangID.find( mnLangID));
-        if (it != theMapLangID.end())
+        MapLangID& rMap = theMapLangID::get();
+        MapLangID::const_iterator it( rMap.find( mnLangID));
+        if (it != rMap.end())
         {
             SAL_INFO( "i18nlangtag", "LanguageTag::registerImpl: found impl for 0x" << ::std::hex << mnLangID);
             pImpl = (*it).second;
@@ -853,7 +863,7 @@ LanguageTag::ImplPtr LanguageTag::registerImpl() const
         {
             SAL_INFO( "i18nlangtag", "LanguageTag::registerImpl: new impl for 0x" << ::std::hex << mnLangID);
             pImpl = std::make_shared<LanguageTagImpl>( *this);
-            theMapLangID.insert( ::std::make_pair( mnLangID, pImpl));
+            rMap.insert( ::std::make_pair( mnLangID, pImpl));
             // Try round-trip.
             if (!pImpl->mbInitializedLocale)
                 pImpl->convertLangToLocale();
@@ -864,7 +874,7 @@ LanguageTag::ImplPtr LanguageTag::registerImpl() const
                 if (!pImpl->mbInitializedBcp47)
                     pImpl->convertLocaleToBcp47();
                 ::std::pair< MapBcp47::const_iterator, bool > res(
-                        theMapBcp47.insert( ::std::make_pair( pImpl->maBcp47, pImpl)));
+                        theMapBcp47::get().insert( ::std::make_pair( pImpl->maBcp47, pImpl)));
                 if (res.second)
                 {
                     SAL_INFO( "i18nlangtag", "LanguageTag::registerImpl: cross-inserted '" << pImpl->maBcp47 << "' for 0x" << ::std::hex << mnLangID);
@@ -885,8 +895,9 @@ LanguageTag::ImplPtr LanguageTag::registerImpl() const
     }
     else if (!maBcp47.isEmpty())
     {
-        MapBcp47::const_iterator it( theMapBcp47.find( maBcp47));
-        if (it != theMapBcp47.end())
+        MapBcp47& rMap = theMapBcp47::get();
+        MapBcp47::const_iterator it( rMap.find( maBcp47));
+        if (it != rMap.end())
         {
             SAL_INFO( "i18nlangtag", "LanguageTag::registerImpl: found impl for '" << maBcp47 << "'");
             pImpl = (*it).second;
@@ -895,14 +906,14 @@ LanguageTag::ImplPtr LanguageTag::registerImpl() const
         {
             SAL_INFO( "i18nlangtag", "LanguageTag::registerImpl: new impl for '" << maBcp47 << "'");
             pImpl = std::make_shared<LanguageTagImpl>( *this);
-            ::std::pair< MapBcp47::iterator, bool > insOrig( theMapBcp47.insert( ::std::make_pair( maBcp47, pImpl)));
+            ::std::pair< MapBcp47::iterator, bool > insOrig( rMap.insert( ::std::make_pair( maBcp47, pImpl)));
             // If changed after canonicalize() also add the resulting tag to
             // the map.
             if (pImpl->synCanonicalize())
             {
                 SAL_INFO( "i18nlangtag", "LanguageTag::registerImpl: canonicalized to '" << pImpl->maBcp47 << "'");
                 ::std::pair< MapBcp47::const_iterator, bool > insCanon(
-                        theMapBcp47.insert( ::std::make_pair( pImpl->maBcp47, pImpl)));
+                        rMap.insert( ::std::make_pair( pImpl->maBcp47, pImpl)));
                 SAL_INFO( "i18nlangtag", "LanguageTag::registerImpl: " << (insCanon.second ? "" : "not ")
                         << "inserted '" << pImpl->maBcp47 << "'");
                 // If the canonicalized tag already existed (was not inserted)
@@ -946,7 +957,7 @@ LanguageTag::ImplPtr LanguageTag::registerImpl() const
                 if (bInsert)
                 {
                     ::std::pair< MapLangID::const_iterator, bool > res(
-                            theMapLangID.insert( ::std::make_pair( pImpl->mnLangID, pImpl)));
+                            theMapLangID::get().insert( ::std::make_pair( pImpl->mnLangID, pImpl)));
                     if (res.second)
                     {
                         SAL_INFO( "i18nlangtag", "LanguageTag::registerImpl: cross-inserted 0x"
@@ -978,7 +989,7 @@ LanguageTag::ImplPtr LanguageTag::registerImpl() const
     // above, so add it.
     if (mbSystemLocale && mbInitializedLangID)
     {
-        theSystemLocale = pImpl;
+        theSystemLocale::get() = pImpl;
         SAL_INFO( "i18nlangtag", "LanguageTag::registerImpl: added system locale 0x"
                 << ::std::hex << pImpl->mnLangID << " '" << pImpl->maBcp47 << "'");
     }
@@ -1688,11 +1699,7 @@ OUString LanguageTagImpl::getVariantsFromLangtag()
 const css::lang::Locale & LanguageTag::getLocale( bool bResolveSystem ) const
 {
     if (!bResolveSystem && mbSystemLocale)
-    {
-        // "static" to be returned as const reference to an empty locale.
-        static const lang::Locale theEmptyLocale;
-        return theEmptyLocale;
-    }
+        return theEmptyLocale::get();
     if (!mbInitializedLocale)
         syncVarsFromImpl();
     if (!mbInitializedLocale)


More information about the Libreoffice-commits mailing list