diff options
author | Andreas Buhr <andreas@andreasbuhr.de> | 2022-06-15 16:14:47 +0200 |
---|---|---|
committer | Oliver Wolff <oliver.wolff@qt.io> | 2022-10-31 12:02:30 +0100 |
commit | ffb9dee1b0954e4d4f9e9791175609a80ecafc31 (patch) | |
tree | a8a12701b366da0650ff264202b101fba9153924 /src/corelib | |
parent | c30c76c84473b8b117b1542e75239973a7bcaf06 (diff) |
Proper clearing of WinRT factory cache
If we use winrt's factories we have to make sure to to clear the factory
cache when one of our dlls is unloaded or we will run into dangling
factory entries which might result in crashes. So we have to make sure
that winrt::clear_factory_cache is called on every dll unload.
In order not to increase compile times and dependencies too much
qfactorycacheregistration_p.h needs to be included in Qt code whenever
we use winrt's factory cache. A rule of thumb being: Include
qfactorycacheregistration_p.h whenever including winrt/base.h.
Other Qt modules which use winrt's factories need to be updated too.
Fixes: QTBUG-103611
Pick-to: 6.2 6.4
Change-Id: I7ab24e4b18bffaca653c5b7f56a66ce99212e339
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Diffstat (limited to 'src/corelib')
-rw-r--r-- | src/corelib/CMakeLists.txt | 6 | ||||
-rw-r--r-- | src/corelib/configure.cmake | 2 | ||||
-rw-r--r-- | src/corelib/platform/windows/qfactorycacheregistration.cpp | 53 | ||||
-rw-r--r-- | src/corelib/platform/windows/qfactorycacheregistration_p.h | 52 | ||||
-rw-r--r-- | src/corelib/text/qlocale_win.cpp | 1 |
5 files changed, 113 insertions, 1 deletions
diff --git a/src/corelib/CMakeLists.txt b/src/corelib/CMakeLists.txt index f9c5690037..f583d3180c 100644 --- a/src/corelib/CMakeLists.txt +++ b/src/corelib/CMakeLists.txt @@ -1015,6 +1015,12 @@ qt_internal_extend_target(Core CONDITION ANDROID platform/android/qandroidnativeinterface.cpp ) +qt_internal_extend_target(Core CONDITION WIN32 + SOURCES + platform/windows/qfactorycacheregistration_p.h + platform/windows/qfactorycacheregistration.cpp +) + qt_internal_extend_target(Core CONDITION HAIKU AND NOT ANDROID SOURCES io/qstandardpaths_haiku.cpp diff --git a/src/corelib/configure.cmake b/src/corelib/configure.cmake index 5563729a5b..a8d6037a7d 100644 --- a/src/corelib/configure.cmake +++ b/src/corelib/configure.cmake @@ -746,7 +746,7 @@ qt_feature("xmlstream" PUBLIC LABEL "XML Streaming APIs" PURPOSE "Provides a simple streaming API for XML." ) -qt_feature("cpp-winrt" PRIVATE +qt_feature("cpp-winrt" PRIVATE PUBLIC LABEL "cpp/winrt base" PURPOSE "basic cpp/winrt language projection support" CONDITION WIN32 AND TEST_cpp_winrt diff --git a/src/corelib/platform/windows/qfactorycacheregistration.cpp b/src/corelib/platform/windows/qfactorycacheregistration.cpp new file mode 100644 index 0000000000..6bd69c66d1 --- /dev/null +++ b/src/corelib/platform/windows/qfactorycacheregistration.cpp @@ -0,0 +1,53 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qfactorycacheregistration_p.h" + +#include <QtCore/QMutex> + +QT_BEGIN_NAMESPACE + +#ifdef QT_USE_FACTORY_CACHE_REGISTRATION + +static QBasicMutex registrationMutex; +static detail::QWinRTFactoryCacheRegistration *firstElement; + +detail::QWinRTFactoryCacheRegistration::QWinRTFactoryCacheRegistration( + QFunctionPointer clearFunction) + : m_clearFunction(clearFunction) +{ + QMutexLocker lock(®istrationMutex); + + // forward pointers + m_next = std::exchange(firstElement, this); + + // backward pointers + m_prevNext = &firstElement; + if (m_next) + m_next->m_prevNext = &m_next; +} + +detail::QWinRTFactoryCacheRegistration::~QWinRTFactoryCacheRegistration() +{ + QMutexLocker lock(®istrationMutex); + + *m_prevNext = m_next; + + if (m_next) + m_next->m_prevNext = m_prevNext; +} + +void detail::QWinRTFactoryCacheRegistration::clearAllCaches() +{ + QMutexLocker lock(®istrationMutex); + + detail::QWinRTFactoryCacheRegistration *element; + + for (element = firstElement; element != nullptr; element = element->m_next) { + element->m_clearFunction(); + } +} + +#endif + +QT_END_NAMESPACE diff --git a/src/corelib/platform/windows/qfactorycacheregistration_p.h b/src/corelib/platform/windows/qfactorycacheregistration_p.h new file mode 100644 index 0000000000..db1582e94b --- /dev/null +++ b/src/corelib/platform/windows/qfactorycacheregistration_p.h @@ -0,0 +1,52 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QFACTORYCACHEREGISTRATION_P_H +#define QFACTORYCACHEREGISTRATION_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/qglobal.h> + +#if !defined(QT_BOOTSTRAPPED) && defined(Q_OS_WIN) && !defined(Q_CC_CLANG) && QT_CONFIG(cpp_winrt) +# define QT_USE_FACTORY_CACHE_REGISTRATION +#endif + +#ifdef QT_USE_FACTORY_CACHE_REGISTRATION + +#include <winrt/base.h> + +QT_BEGIN_NAMESPACE + +namespace detail { + +class QWinRTFactoryCacheRegistration +{ +public: + Q_CORE_EXPORT explicit QWinRTFactoryCacheRegistration(QFunctionPointer clearFunction); + Q_CORE_EXPORT ~QWinRTFactoryCacheRegistration(); + Q_CORE_EXPORT static void clearAllCaches(); + + Q_DISABLE_COPY_MOVE(QWinRTFactoryCacheRegistration) +private: + QWinRTFactoryCacheRegistration **m_prevNext = nullptr; + QWinRTFactoryCacheRegistration *m_next = nullptr; + QFunctionPointer m_clearFunction; +}; + +inline QWinRTFactoryCacheRegistration reg([]() noexcept { winrt::clear_factory_cache(); }); +} + +QT_END_NAMESPACE + +#endif +#endif // QFACTORYCACHEREGISTRATION_P_H diff --git a/src/corelib/text/qlocale_win.cpp b/src/corelib/text/qlocale_win.cpp index 3a3ae443c6..821369ff89 100644 --- a/src/corelib/text/qlocale_win.cpp +++ b/src/corelib/text/qlocale_win.cpp @@ -21,6 +21,7 @@ #if QT_CONFIG(cpp_winrt) # include <winrt/base.h> +# include <QtCore/private/qfactorycacheregistration_p.h> // Workaround for Windows SDK bug. // See https://github.com/microsoft/Windows.UI.Composition-Win32-Samples/issues/47 namespace winrt::impl |