summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJøger Hansegård <joger.hansegard@qt.io>2024-01-22 11:32:10 +0100
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2024-01-22 19:02:06 +0000
commitea027cb821ce77a3703a66e68e891f481ae25d76 (patch)
tree8b8b88e24c486ebcce8d847ec37d4e7477d66a58
parentbb5bd27ce1011753d43bff68a6e7ee2e98bf3a37 (diff)
Fix abrupt termination during static destruction in QtMultimedia
Breaking change: After this change, QtMultimedia requires a QCoreApplication to access or enumerate media devices (microphone, speakers, and camera). During destruction, a Windows application using QtMultimedia could exit with success return code without having called all static destructors. The root cause of the issue was that the internal QWindowsMediaDevices singleton was making outgoing COM-calls during static destruction. This is not handled well by the COM runtime, and resulted in NtTerminateProcess being called from within the implementation of Microsoft IMMDeviceEnumerator::UnregisterEndpointNotificationCallback. After this point, destructors were never called even if the application returned 0, indicating success. This patch fixes this issue by ensuring that the QWindowMediaDevices instance are deleted when the QCoreApplication is terminated, instead of waiting until static destruction. If no QCoreApplication exists, a warning is emitted, and destruction is executed as before, with possible interruption of static destructors. Fixes: QTBUG-120198 Pick-to: 6.5 Change-Id: I52a2b355052d61333fbff382dc4d4cd059d99d52 Reviewed-by: Artem Dyomin <artem.dyomin@qt.io> (cherry picked from commit 44f1e17d2843851d00c546f944582ab3fb409a45) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> (cherry picked from commit 073e0114241a8f6cf747290ec641c9332251f3ba)
-rw-r--r--src/multimedia/platform/qplatformmediadevices.cpp25
-rw-r--r--src/multimedia/windows/qwindowsmediadevices.cpp3
2 files changed, 25 insertions, 3 deletions
diff --git a/src/multimedia/platform/qplatformmediadevices.cpp b/src/multimedia/platform/qplatformmediadevices.cpp
index f971fb4c3..a9d591ee8 100644
--- a/src/multimedia/platform/qplatformmediadevices.cpp
+++ b/src/multimedia/platform/qplatformmediadevices.cpp
@@ -12,6 +12,7 @@
#include <qmutex.h>
#include <qloggingcategory.h>
+#include <QtCore/qcoreapplication.h>
#if defined(Q_OS_ANDROID)
#include <qandroidmediadevices_p.h>
@@ -33,18 +34,26 @@
QT_BEGIN_NAMESPACE
namespace {
-struct DevicesHolder {
- ~DevicesHolder()
+
+struct DevicesHolder
+{
+ ~DevicesHolder() { reset(); }
+
+ void reset()
{
QMutexLocker locker(&mutex);
+
delete nativeInstance;
nativeInstance = nullptr;
instance = nullptr;
}
+
QBasicMutex mutex;
QPlatformMediaDevices *instance = nullptr;
QPlatformMediaDevices *nativeInstance = nullptr;
-} devicesHolder;
+};
+
+DevicesHolder devicesHolder;
}
@@ -72,6 +81,16 @@ QPlatformMediaDevices *QPlatformMediaDevices::instance()
devicesHolder.nativeInstance = new QPlatformMediaDevices;
#endif
+ if (!QCoreApplication::instance()) {
+ // QTBUG-120198: Destructors are not called when shutting down
+ // application with Windows backend.
+ qWarning("Accessing QMediaDevices without a QCoreApplication");
+ } else {
+ connect(qApp, &QObject::destroyed, devicesHolder.nativeInstance, []() {
+ devicesHolder.reset();
+ });
+ }
+
devicesHolder.instance = devicesHolder.nativeInstance;
return devicesHolder.instance;
}
diff --git a/src/multimedia/windows/qwindowsmediadevices.cpp b/src/multimedia/windows/qwindowsmediadevices.cpp
index 4dc27f513..fccb7f20f 100644
--- a/src/multimedia/windows/qwindowsmediadevices.cpp
+++ b/src/multimedia/windows/qwindowsmediadevices.cpp
@@ -162,6 +162,9 @@ QWindowsMediaDevices::QWindowsMediaDevices()
QWindowsMediaDevices::~QWindowsMediaDevices()
{
if (m_deviceEnumerator) {
+ // Note: Calling UnregisterEndpointNotificationCallback after CoUninitialize
+ // will abruptly terminate application, preventing remaining destructors from
+ // being called (QTBUG-120198).
m_deviceEnumerator->UnregisterEndpointNotificationCallback(m_notificationClient.Get());
}
if (m_warmUpAudioClient) {