drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx | 20 ++-- drawinglayer/source/processor2d/vclmetafileprocessor2d.hxx | 3 editeng/source/editeng/eerdll.cxx | 10 +- i18npool/source/localedata/LocaleNode.cxx | 60 ++++++------- i18npool/source/localedata/localedata.cxx | 51 +++-------- include/editeng/eerdll.hxx | 1 svx/CppunitTest_svx_styles.mk | 1 sw/CppunitTest_sw_uibase_uiview.mk | 1 8 files changed, 71 insertions(+), 76 deletions(-)
New commits: commit 1a253362f6d1e1909913dce298630c92d431e41e Author: Noel Grandin <noel.gran...@collabora.co.uk> AuthorDate: Wed Jun 14 13:32:01 2023 +0200 Commit: Noel Grandin <noel.gran...@collabora.co.uk> CommitDate: Thu Jun 15 18:15:18 2023 +0200 speed up startup time by avoid conversion of static locale data from sal_Unicode to OUString data - we can declare the data as OUStringConstExpr arrays and then no conversion is necessary. Here we trigger a problem - EditDLL has static data that tends to get torn down __after__ the i18npool shared library has been removed from memory, which means it tries to access OUStringLiteral objects that no longer exists. So use vcl::DeleteOnExit to explicitly clear that on application shutdown. Change-Id: Ie4bfcef7eb4656316ea825474ac42f85844d1dcc Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153060 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk> diff --git a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx index 1b411d16f443..794f8085f9c8 100644 --- a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx +++ b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx @@ -520,7 +520,8 @@ void VclMetafileProcessor2D::popList() } // init static break iterator -uno::Reference<css::i18n::XBreakIterator> VclMetafileProcessor2D::mxBreakIterator; +vcl::DeleteOnDeinit<uno::Reference<css::i18n::XBreakIterator>> + VclMetafileProcessor2D::mxBreakIterator; VclMetafileProcessor2D::VclMetafileProcessor2D(const geometry::ViewInformation2D& rViewInformation, OutputDevice& rOutDev) @@ -1470,12 +1471,13 @@ void VclMetafileProcessor2D::processTextSimplePortionPrimitive2D( // #i101169# if(pTextDecoratedCandidate) { // support for TEXT_ MetaFile actions only for decorated texts - if (!mxBreakIterator.is()) + if (!mxBreakIterator.get() || !mxBreakIterator.get()->get()) { uno::Reference<uno::XComponentContext> xContext( ::comphelper::getProcessComponentContext()); - mxBreakIterator = i18n::BreakIterator::create(xContext); + mxBreakIterator.set(i18n::BreakIterator::create(xContext)); } + auto& rBreakIterator = *mxBreakIterator.get()->get(); const OUString& rTxt = rTextCandidate.getText(); const sal_Int32 nTextLength(rTextCandidate.getTextLength()); // rTxt.getLength()); @@ -1486,13 +1488,13 @@ void VclMetafileProcessor2D::processTextSimplePortionPrimitive2D( const sal_Int32 nTextPosition(rTextCandidate.getTextPosition()); sal_Int32 nDone; - sal_Int32 nNextCellBreak(mxBreakIterator->nextCharacters( + sal_Int32 nNextCellBreak(rBreakIterator.nextCharacters( rTxt, nTextPosition, rLocale, css::i18n::CharacterIteratorMode::SKIPCELL, 0, nDone)); - css::i18n::Boundary nNextWordBoundary(mxBreakIterator->getWordBoundary( + css::i18n::Boundary nNextWordBoundary(rBreakIterator.getWordBoundary( rTxt, nTextPosition, rLocale, css::i18n::WordType::ANY_WORD, true)); sal_Int32 nNextSentenceBreak( - mxBreakIterator->endOfSentence(rTxt, nTextPosition, rLocale)); + rBreakIterator.endOfSentence(rTxt, nTextPosition, rLocale)); const OString aCommentStringA("XTEXT_EOC"); const OString aCommentStringB("XTEXT_EOW"); const OString aCommentStringC("XTEXT_EOS"); @@ -1504,21 +1506,21 @@ void VclMetafileProcessor2D::processTextSimplePortionPrimitive2D( { mpMetaFile->AddAction( new MetaCommentAction(aCommentStringA, i - nTextPosition)); - nNextCellBreak = mxBreakIterator->nextCharacters( + nNextCellBreak = rBreakIterator.nextCharacters( rTxt, i, rLocale, css::i18n::CharacterIteratorMode::SKIPCELL, 1, nDone); } if (i == nNextWordBoundary.endPos) { mpMetaFile->AddAction( new MetaCommentAction(aCommentStringB, i - nTextPosition)); - nNextWordBoundary = mxBreakIterator->getWordBoundary( + nNextWordBoundary = rBreakIterator.getWordBoundary( rTxt, i + 1, rLocale, css::i18n::WordType::ANY_WORD, true); } if (i == nNextSentenceBreak) { mpMetaFile->AddAction( new MetaCommentAction(aCommentStringC, i - nTextPosition)); - nNextSentenceBreak = mxBreakIterator->endOfSentence(rTxt, i + 1, rLocale); + nNextSentenceBreak = rBreakIterator.endOfSentence(rTxt, i + 1, rLocale); } } } diff --git a/drawinglayer/source/processor2d/vclmetafileprocessor2d.hxx b/drawinglayer/source/processor2d/vclmetafileprocessor2d.hxx index 730b7aac11f2..c315281ebf61 100644 --- a/drawinglayer/source/processor2d/vclmetafileprocessor2d.hxx +++ b/drawinglayer/source/processor2d/vclmetafileprocessor2d.hxx @@ -25,6 +25,7 @@ #include <com/sun/star/i18n/XBreakIterator.hpp> #include <basegfx/polygon/b2dpolypolygon.hxx> #include <vcl/pdfextoutdevdata.hxx> // vcl::PDFExtOutDevData support +#include <vcl/lazydelete.hxx> class GDIMetaFile; namespace tools @@ -175,7 +176,7 @@ private: constructed VclMetafileProcessor2D. It's still incarnated on demand, but exists for OOo runtime now by purpose. */ - static css::uno::Reference<css::i18n::XBreakIterator> mxBreakIterator; + static vcl::DeleteOnDeinit<css::uno::Reference<css::i18n::XBreakIterator>> mxBreakIterator; /* vcl::PDFExtOutDevData support For the first step, some extra actions at vcl::PDFExtOutDevData need to diff --git a/editeng/source/editeng/eerdll.cxx b/editeng/source/editeng/eerdll.cxx index b7120bd1befd..f6a1cbc049c2 100644 --- a/editeng/source/editeng/eerdll.cxx +++ b/editeng/source/editeng/eerdll.cxx @@ -64,13 +64,19 @@ #include <editeng/forbiddencharacterstable.hxx> #include <editeng/justifyitem.hxx> #include <tools/mapunit.hxx> +#include <vcl/lazydelete.hxx> using namespace ::com::sun::star; EditDLL& EditDLL::Get() { - static EditDLL theEditDLL; - return theEditDLL; + /** + Prevent use-after-free errors during application shutdown. + Previously this data was function-static, but then data in i18npool would + be torn down before the destructor here ran, causing a crash. + */ + static vcl::DeleteOnDeinit< EditDLL > gaEditDll; + return *gaEditDll.get(); } DefItems::DefItems() diff --git a/i18npool/source/localedata/LocaleNode.cxx b/i18npool/source/localedata/LocaleNode.cxx index 49024a6bc97f..d797c45c53b6 100644 --- a/i18npool/source/localedata/LocaleNode.cxx +++ b/i18npool/source/localedata/LocaleNode.cxx @@ -2071,7 +2071,7 @@ void LCTransliterationNode::generateCode (const OFileWriter &of) const OUString useLocale = getAttr().getValueByName("ref"); if (!useLocale.isEmpty()) { useLocale = useLocale.replace( '-', '_'); - of.writeRefFunction("getTransliterations_", useLocale); + of.writeOUStringRefFunction("getTransliterations_", useLocale); return; } sal_Int16 nbOfModules = 0; @@ -2080,20 +2080,20 @@ void LCTransliterationNode::generateCode (const OFileWriter &of) const for ( sal_Int32 i = 0; i < getNumberOfChildren(); i++,nbOfModules++) { LocaleNode * transNode = getChildAt (i); str = transNode->getAttr().getValueByIndex(0); - of.writeParameter("Transliteration", str, nbOfModules); + of.writeOUStringLiteralParameter("Transliteration", str, nbOfModules); } of.writeAsciiString("static const sal_Int16 nbOfTransliterations = "); of.writeInt(nbOfModules); of.writeAsciiString(";\n\n"); - of.writeAsciiString("\nstatic const sal_Unicode* LCTransliterationsArray[] = {\n"); + of.writeAsciiString("\nstatic constexpr rtl::OUStringConstExpr LCTransliterationsArray[] = {\n"); for( sal_Int16 i = 0; i < nbOfModules; i++) { of.writeAsciiString("\tTransliteration"); of.writeInt(i); of.writeAsciiString(",\n"); } of.writeAsciiString("};\n\n"); - of.writeFunction("getTransliterations_", "nbOfTransliterations", "LCTransliterationsArray"); + of.writeOUStringFunction("getTransliterations_", "nbOfTransliterations", "LCTransliterationsArray"); } namespace { @@ -2125,9 +2125,9 @@ void LCMiscNode::generateCode (const OFileWriter &of) const OUString useLocale = getAttr().getValueByName("ref"); if (!useLocale.isEmpty()) { useLocale = useLocale.replace( '-', '_'); - of.writeRefFunction("getForbiddenCharacters_", useLocale); - of.writeRefFunction("getBreakIteratorRules_", useLocale); - of.writeRefFunction("getReservedWords_", useLocale); + of.writeOUStringRefFunction("getForbiddenCharacters_", useLocale); + of.writeOUStringRefFunction("getBreakIteratorRules_", useLocale); + of.writeOUStringRefFunction("getReservedWords_", useLocale); return; } const LocaleNode * reserveNode = findNode("ReservedWords"); @@ -2155,7 +2155,7 @@ void LCMiscNode::generateCode (const OFileWriter &of) const ++nError; fprintf( stderr, "Error: No content for ReservedWords %s.\n", ReserveWord[i].name); } - of.writeParameter("ReservedWord", str, nbOfWords); + of.writeOUStringLiteralParameter("ReservedWord", str, nbOfWords); // "true", ..., "below" trigger untranslated warning. if (!bEnglishLocale && curNode && i <= 7 && str.equalsIgnoreAsciiCaseAscii( ReserveWord[i].value)) @@ -2168,52 +2168,52 @@ void LCMiscNode::generateCode (const OFileWriter &of) const of.writeAsciiString("static const sal_Int16 nbOfReservedWords = "); of.writeInt(nbOfWords); of.writeAsciiString(";\n\n"); - of.writeAsciiString("\nstatic const sal_Unicode* LCReservedWordsArray[] = {\n"); + of.writeAsciiString("\nstatic constexpr rtl::OUStringConstExpr LCReservedWordsArray[] = {\n"); for( i = 0; i < nbOfWords; i++) { of.writeAsciiString("\tReservedWord"); of.writeInt(i); of.writeAsciiString(",\n"); } of.writeAsciiString("};\n\n"); - of.writeFunction("getReservedWords_", "nbOfReservedWords", "LCReservedWordsArray"); + of.writeOUStringFunction("getReservedWords_", "nbOfReservedWords", "LCReservedWordsArray"); if (forbidNode) { - of.writeParameter( "forbiddenBegin", forbidNode -> getChildAt(0)->getValue()); - of.writeParameter( "forbiddenEnd", forbidNode -> getChildAt(1)->getValue()); - of.writeParameter( "hangingChars", forbidNode -> getChildAt(2)->getValue()); + of.writeOUStringLiteralParameter( "forbiddenBegin", forbidNode -> getChildAt(0)->getValue()); + of.writeOUStringLiteralParameter( "forbiddenEnd", forbidNode -> getChildAt(1)->getValue()); + of.writeOUStringLiteralParameter( "hangingChars", forbidNode -> getChildAt(2)->getValue()); } else { - of.writeParameter( "forbiddenBegin", std::u16string_view()); - of.writeParameter( "forbiddenEnd", std::u16string_view()); - of.writeParameter( "hangingChars", std::u16string_view()); + of.writeOUStringLiteralParameter( "forbiddenBegin", std::u16string_view()); + of.writeOUStringLiteralParameter( "forbiddenEnd", std::u16string_view()); + of.writeOUStringLiteralParameter( "hangingChars", std::u16string_view()); } - of.writeAsciiString("\nstatic const sal_Unicode* LCForbiddenCharactersArray[] = {\n"); + of.writeAsciiString("\nstatic constexpr rtl::OUStringConstExpr LCForbiddenCharactersArray[] = {\n"); of.writeAsciiString("\tforbiddenBegin,\n"); of.writeAsciiString("\tforbiddenEnd,\n"); of.writeAsciiString("\thangingChars\n"); of.writeAsciiString("};\n\n"); - of.writeFunction("getForbiddenCharacters_", "3", "LCForbiddenCharactersArray"); + of.writeOUStringFunction("getForbiddenCharacters_", "3", "LCForbiddenCharactersArray"); if (breakNode) { - of.writeParameter( "EditMode", breakNode -> getChildAt(0)->getValue()); - of.writeParameter( "DictionaryMode", breakNode -> getChildAt(1)->getValue()); - of.writeParameter( "WordCountMode", breakNode -> getChildAt(2)->getValue()); - of.writeParameter( "CharacterMode", breakNode -> getChildAt(3)->getValue()); - of.writeParameter( "LineMode", breakNode -> getChildAt(4)->getValue()); + of.writeOUStringLiteralParameter( "EditMode", breakNode -> getChildAt(0)->getValue()); + of.writeOUStringLiteralParameter( "DictionaryMode", breakNode -> getChildAt(1)->getValue()); + of.writeOUStringLiteralParameter( "WordCountMode", breakNode -> getChildAt(2)->getValue()); + of.writeOUStringLiteralParameter( "CharacterMode", breakNode -> getChildAt(3)->getValue()); + of.writeOUStringLiteralParameter( "LineMode", breakNode -> getChildAt(4)->getValue()); } else { - of.writeParameter( "EditMode", std::u16string_view()); - of.writeParameter( "DictionaryMode", std::u16string_view()); - of.writeParameter( "WordCountMode", std::u16string_view()); - of.writeParameter( "CharacterMode", std::u16string_view()); - of.writeParameter( "LineMode", std::u16string_view()); + of.writeOUStringLiteralParameter( "EditMode", std::u16string_view()); + of.writeOUStringLiteralParameter( "DictionaryMode", std::u16string_view()); + of.writeOUStringLiteralParameter( "WordCountMode", std::u16string_view()); + of.writeOUStringLiteralParameter( "CharacterMode", std::u16string_view()); + of.writeOUStringLiteralParameter( "LineMode", std::u16string_view()); } - of.writeAsciiString("\nstatic const sal_Unicode* LCBreakIteratorRulesArray[] = {\n"); + of.writeAsciiString("\nstatic constexpr rtl::OUStringConstExpr LCBreakIteratorRulesArray[] = {\n"); of.writeAsciiString("\tEditMode,\n"); of.writeAsciiString("\tDictionaryMode,\n"); of.writeAsciiString("\tWordCountMode,\n"); of.writeAsciiString("\tCharacterMode,\n"); of.writeAsciiString("\tLineMode\n"); of.writeAsciiString("};\n\n"); - of.writeFunction("getBreakIteratorRules_", "5", "LCBreakIteratorRulesArray"); + of.writeOUStringFunction("getBreakIteratorRules_", "5", "LCBreakIteratorRulesArray"); } diff --git a/i18npool/source/localedata/localedata.cxx b/i18npool/source/localedata/localedata.cxx index 5b6c0c214bbb..7316b66fce7f 100644 --- a/i18npool/source/localedata/localedata.cxx +++ b/i18npool/source/localedata/localedata.cxx @@ -1105,19 +1105,12 @@ LocaleDataImpl::getFollowPageWords( const Locale& rLocale ) Sequence< OUString > SAL_CALL LocaleDataImpl::getTransliterations( const Locale& rLocale ) { - MyFunc_Type func = reinterpret_cast<MyFunc_Type>(getFunctionSymbol( rLocale, "getTransliterations" )); + MyFuncOUString_Type func = reinterpret_cast<MyFuncOUString_Type>(getFunctionSymbol( rLocale, "getTransliterations" )); if ( func ) { sal_Int16 transliterationsCount = 0; - sal_Unicode **transliterationsArray = func(transliterationsCount); - - Sequence< OUString > seq(transliterationsCount); - auto seqRange = asNonConstRange(seq); - for(int i = 0; i < transliterationsCount; i++) { - OUString elem(transliterationsArray[i]); - seqRange[i] = elem; - } - return seq; + const OUString *transliterationsArray = func(transliterationsCount); + return Sequence< OUString >(transliterationsArray, transliterationsCount); } else { return {}; @@ -1153,13 +1146,14 @@ LocaleDataImpl::getLanguageCountryInfo( const Locale& rLocale ) ForbiddenCharacters SAL_CALL LocaleDataImpl::getForbiddenCharacters( const Locale& rLocale ) { - MyFunc_Type func = reinterpret_cast<MyFunc_Type>(getFunctionSymbol( rLocale, "getForbiddenCharacters" )); + MyFuncOUString_Type func = reinterpret_cast<MyFuncOUString_Type>(getFunctionSymbol( rLocale, "getForbiddenCharacters" )); if ( func ) { sal_Int16 LCForbiddenCharactersCount = 0; - sal_Unicode **LCForbiddenCharactersArray = func(LCForbiddenCharactersCount); + OUString const *LCForbiddenCharactersArray = func(LCForbiddenCharactersCount); + assert(LCForbiddenCharactersCount == 3); ForbiddenCharacters chars{ - OUString(LCForbiddenCharactersArray[0]), OUString(LCForbiddenCharactersArray[1])}; + LCForbiddenCharactersArray[0], LCForbiddenCharactersArray[1]}; return chars; } else { @@ -1171,12 +1165,13 @@ LocaleDataImpl::getForbiddenCharacters( const Locale& rLocale ) OUString LocaleDataImpl::getHangingCharacters( const Locale& rLocale ) { - MyFunc_Type func = reinterpret_cast<MyFunc_Type>(getFunctionSymbol( rLocale, "getForbiddenCharacters" )); + MyFuncOUString_Type func = reinterpret_cast<MyFuncOUString_Type>(getFunctionSymbol( rLocale, "getForbiddenCharacters" )); if ( func ) { sal_Int16 LCForbiddenCharactersCount = 0; - sal_Unicode **LCForbiddenCharactersArray = func(LCForbiddenCharactersCount); - return OUString(LCForbiddenCharactersArray[2]); + const OUString *LCForbiddenCharactersArray = func(LCForbiddenCharactersCount); + assert(LCForbiddenCharactersCount == 3); + return LCForbiddenCharactersArray[2]; } return OUString(); @@ -1185,18 +1180,12 @@ LocaleDataImpl::getHangingCharacters( const Locale& rLocale ) Sequence< OUString > LocaleDataImpl::getBreakIteratorRules( const Locale& rLocale ) { - MyFunc_Type func = reinterpret_cast<MyFunc_Type>(getFunctionSymbol( rLocale, "getBreakIteratorRules" )); + MyFuncOUString_Type func = reinterpret_cast<MyFuncOUString_Type>(getFunctionSymbol( rLocale, "getBreakIteratorRules" )); if ( func ) { sal_Int16 LCBreakIteratorRuleCount = 0; - sal_Unicode **LCBreakIteratorRulesArray = func(LCBreakIteratorRuleCount); - Sequence< OUString > seq(LCBreakIteratorRuleCount); - auto seqRange = asNonConstRange(seq); - for(int i = 0; i < LCBreakIteratorRuleCount; i++) { - OUString elem(LCBreakIteratorRulesArray[i]); - seqRange[i] = elem; - } - return seq; + OUString const *LCBreakIteratorRulesArray = func(LCBreakIteratorRuleCount); + return Sequence< OUString >(LCBreakIteratorRulesArray, LCBreakIteratorRuleCount); } else { return {}; @@ -1207,18 +1196,12 @@ LocaleDataImpl::getBreakIteratorRules( const Locale& rLocale ) Sequence< OUString > SAL_CALL LocaleDataImpl::getReservedWord( const Locale& rLocale ) { - MyFunc_Type func = reinterpret_cast<MyFunc_Type>(getFunctionSymbol( rLocale, "getReservedWords" )); + MyFuncOUString_Type func = reinterpret_cast<MyFuncOUString_Type>(getFunctionSymbol( rLocale, "getReservedWords" )); if ( func ) { sal_Int16 LCReservedWordsCount = 0; - sal_Unicode **LCReservedWordsArray = func(LCReservedWordsCount); - Sequence< OUString > seq(LCReservedWordsCount); - auto seqRange = asNonConstRange(seq); - for(int i = 0; i < LCReservedWordsCount; i++) { - OUString elem(LCReservedWordsArray[i]); - seqRange[i] = elem; - } - return seq; + OUString const *LCReservedWordsArray = func(LCReservedWordsCount); + return Sequence< OUString >(LCReservedWordsArray, LCReservedWordsCount); } else { return {}; diff --git a/include/editeng/eerdll.hxx b/include/editeng/eerdll.hxx index b77d6a0d4703..017ff72972a4 100644 --- a/include/editeng/eerdll.hxx +++ b/include/editeng/eerdll.hxx @@ -24,6 +24,7 @@ #include <rtl/ustring.hxx> #include <unotools/resmgr.hxx> #include <memory> +#include <mutex> class GlobalEditData; namespace editeng diff --git a/svx/CppunitTest_svx_styles.mk b/svx/CppunitTest_svx_styles.mk index 9d5cccabb8b9..69f6a0953850 100644 --- a/svx/CppunitTest_svx_styles.mk +++ b/svx/CppunitTest_svx_styles.mk @@ -24,6 +24,7 @@ $(eval $(call gb_CppunitTest_use_libraries,svx_styles, \ cppu \ cppuhelper \ docmodel \ + editeng \ svx \ sal \ subsequenttest \ diff --git a/sw/CppunitTest_sw_uibase_uiview.mk b/sw/CppunitTest_sw_uibase_uiview.mk index 867ea19219b4..3a5f8aafef05 100644 --- a/sw/CppunitTest_sw_uibase_uiview.mk +++ b/sw/CppunitTest_sw_uibase_uiview.mk @@ -21,6 +21,7 @@ $(eval $(call gb_CppunitTest_use_libraries,sw_uibase_uiview, \ comphelper \ cppu \ cppuhelper \ + editeng \ sal \ sfx \ subsequenttest \