comphelper/source/misc/configuration.cxx | 59 ++++++++++++++----------------- include/comphelper/configuration.hxx | 20 ++++++++-- 2 files changed, 44 insertions(+), 35 deletions(-)
New commits: commit 203ad037ccb9fdebffea4f622229ded90635eb8b Author: Noel Grandin <noelgran...@gmail.com> AuthorDate: Tue Dec 27 16:25:25 2022 +0200 Commit: Noel Grandin <noel.gran...@collabora.co.uk> CommitDate: Wed Dec 28 12:01:55 2022 +0000 try to fix shutdown crashes in ConfigurationWrapper associated with commit 7df433cdc33b4d6ba38eafad9282d015571433ef optimize ConfigurationProperty::get() it seems it introduced https://crashreport.libreoffice.org/stats/signature/void%20rtl::str::release%3C_rtl_uString%3E(_rtl_uString*) which, at the moment, is the most reported crash in https://crashreport.libreoffice.org/stats/version/7.4.3.2 We need to tie the lifetime of ConfigurationWrapper and the cache objects together, so they die as one unit, otherwise the unpredicatable ordering of destruction of static objects is a problem. Change-Id: I80db5a4c28510a68f40b919902b01f3981e32bfb Reviewed-on: https://gerrit.libreoffice.org/c/core/+/144840 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk> (cherry picked from commit 1b9ca3689dab4deaea20be511eb942674bbbc481) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/144807 diff --git a/comphelper/source/misc/configuration.cxx b/comphelper/source/misc/configuration.cxx index 1d6517fbb26d..b84f705f1db0 100644 --- a/comphelper/source/misc/configuration.cxx +++ b/comphelper/source/misc/configuration.cxx @@ -10,9 +10,6 @@ #include <sal/config.h> #include <cassert> -#include <mutex> -#include <string_view> -#include <unordered_map> #include <com/sun/star/beans/NamedValue.hpp> #include <com/sun/star/beans/PropertyAttribute.hpp> @@ -24,11 +21,12 @@ #include <com/sun/star/container/XHierarchicalNameReplace.hpp> #include <com/sun/star/container/XNameAccess.hpp> #include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/util/XChangesListener.hpp> +#include <com/sun/star/util/XChangesNotifier.hpp> +#include <com/sun/star/lang/DisposedException.hpp> #include <com/sun/star/lang/XLocalizable.hpp> #include <com/sun/star/uno/Any.hxx> #include <com/sun/star/uno/Reference.hxx> -#include <com/sun/star/util/XChangesListener.hpp> -#include <com/sun/star/util/XChangesNotifier.hpp> #include <comphelper/solarmutex.hxx> #include <comphelper/configuration.hxx> #include <comphelper/configurationlistener.hxx> @@ -109,37 +107,32 @@ comphelper::detail::ConfigurationWrapper::get() return WRAPPER; } -namespace -{ -std::mutex gMutex; -std::unordered_map<OUString, css::uno::Any> gPropertyCache; -css::uno::Reference< css::util::XChangesNotifier > gNotifier; -css::uno::Reference< css::util::XChangesListener > gListener; - -class ConfigurationChangesListener +class comphelper::detail::ConfigurationChangesListener : public ::cppu::WeakImplHelper<css::util::XChangesListener> { + comphelper::detail::ConfigurationWrapper& mrConfigurationWrapper; public: - ConfigurationChangesListener() + ConfigurationChangesListener(comphelper::detail::ConfigurationWrapper& rWrapper) + : mrConfigurationWrapper(rWrapper) {} // util::XChangesListener virtual void SAL_CALL changesOccurred( const css::util::ChangesEvent& ) override { - std::scoped_lock aGuard(gMutex); - gPropertyCache.clear(); + std::scoped_lock aGuard(mrConfigurationWrapper.maMutex); + mrConfigurationWrapper.maPropertyCache.clear(); } virtual void SAL_CALL disposing(const css::lang::EventObject&) override { - std::scoped_lock aGuard(gMutex); - gPropertyCache.clear(); + std::scoped_lock aGuard(mrConfigurationWrapper.maMutex); + mrConfigurationWrapper.mbDisposed = true; + mrConfigurationWrapper.maPropertyCache.clear(); } }; -} // namespace - comphelper::detail::ConfigurationWrapper::ConfigurationWrapper(): context_(comphelper::getProcessComponentContext()), - access_(css::configuration::ReadWriteAccess::create(context_, "*")) + access_(css::configuration::ReadWriteAccess::create(context_, "*")), + mbDisposed(false) { // Set up a configuration notifier to invalidate the cache as needed. try @@ -156,10 +149,10 @@ comphelper::detail::ConfigurationWrapper::ConfigurationWrapper(): = xConfigProvider->createInstanceWithArguments(u"com.sun.star.configuration.ConfigurationAccess", params); - gNotifier = css::uno::Reference< css::util::XChangesNotifier >(xCfg, css::uno::UNO_QUERY); - assert(gNotifier.is()); - gListener = css::uno::Reference< ConfigurationChangesListener >(new ConfigurationChangesListener()); - gNotifier->addChangesListener(gListener); + maNotifier = css::uno::Reference< css::util::XChangesNotifier >(xCfg, css::uno::UNO_QUERY); + assert(maNotifier.is()); + maListener = css::uno::Reference< ConfigurationChangesListener >(new ConfigurationChangesListener(*this)); + maNotifier->addChangesListener(maListener); } catch(const css::uno::Exception&) { @@ -169,9 +162,9 @@ comphelper::detail::ConfigurationWrapper::ConfigurationWrapper(): comphelper::detail::ConfigurationWrapper::~ConfigurationWrapper() { - gPropertyCache.clear(); - gNotifier.clear(); - gListener.clear(); + maPropertyCache.clear(); + maNotifier.clear(); + maListener.clear(); } bool comphelper::detail::ConfigurationWrapper::isReadOnly(OUString const & path) @@ -185,10 +178,12 @@ bool comphelper::detail::ConfigurationWrapper::isReadOnly(OUString const & path) css::uno::Any comphelper::detail::ConfigurationWrapper::getPropertyValue(OUString const& path) const { - std::scoped_lock aGuard(gMutex); + std::scoped_lock aGuard(maMutex); + if (mbDisposed) + throw css::lang::DisposedException(); // Cache the configuration access, since some of the keys are used in hot code. - auto it = gPropertyCache.find(path); - if( it != gPropertyCache.end()) + auto it = maPropertyCache.find(path); + if( it != maPropertyCache.end()) return it->second; sal_Int32 idx = path.lastIndexOf("/"); @@ -199,7 +194,7 @@ css::uno::Any comphelper::detail::ConfigurationWrapper::getPropertyValue(OUStrin css::uno::Reference<css::container::XNameAccess> access( access_->getByHierarchicalName(parentPath), css::uno::UNO_QUERY_THROW); css::uno::Any property = access->getByName(childName); - gPropertyCache.emplace(path, property); + maPropertyCache.emplace(path, property); return property; } diff --git a/include/comphelper/configuration.hxx b/include/comphelper/configuration.hxx index 3b8f8f1f7e93..45228b700944 100644 --- a/include/comphelper/configuration.hxx +++ b/include/comphelper/configuration.hxx @@ -12,15 +12,16 @@ #include <sal/config.h> -#include <optional> -#include <string_view> - #include <com/sun/star/uno/Any.hxx> #include <com/sun/star/uno/Reference.h> #include <comphelper/comphelperdllapi.h> #include <comphelper/processfactory.hxx> #include <sal/types.h> #include <memory> +#include <mutex> +#include <optional> +#include <string_view> +#include <unordered_map> namespace com::sun::star { namespace configuration { class XReadWriteAccess; } @@ -31,6 +32,10 @@ namespace com::sun::star { class XNameContainer; } namespace uno { class XComponentContext; } + namespace util { + class XChangesListener; + class XChangesNotifier; + } } namespace comphelper { @@ -80,8 +85,11 @@ private: namespace detail { +class ConfigurationChangesListener; + /// @internal class COMPHELPER_DLLPUBLIC ConfigurationWrapper { +friend class ConfigurationChangesListener; public: static ConfigurationWrapper const & get(); @@ -135,6 +143,12 @@ private: // css.beans.XHierarchicalPropertySetInfo), but then // configmgr::Access::asProperty() would report all properties as // READONLY, so isReadOnly() would not work + + mutable std::mutex maMutex; + bool mbDisposed; + mutable std::unordered_map<OUString, css::uno::Any> maPropertyCache; + css::uno::Reference< css::util::XChangesNotifier > maNotifier; + css::uno::Reference< css::util::XChangesListener > maListener; }; /// @internal