Bug 1650277 - P2. Ensure the CubebDeviceEnumerator is shutdown after the MTAThread. r=kinetik

On Windows the CubebDeviceEnumerator needs to run on an MTA thread; to achieve that goal we use the EnsureMTA utility.
EnsureMTA relies on a MTA thread to exist which will be destroyed when XPCOM shuts down ; as such we must shutdown the CubebDeviceEnumerator during the same shutdown phase.

ClearOnShutdown registrars are processed in LIFO order, so as the CubebDeviceEnumerator constructor uses EnsureMTA we are guaranteed that the CubebDeviceEnumerator clearOnShutdown will be processed before the EnsureMTA thread shutdown.
The CubebDeviceEnumerator needs to be shutdown before cubeb; which is also guaranteed as the cubeb instance is destroyed during the final XPCOM shutdown stage.

Fix GetSafety() thread-safety.

CubebDeviceEnumerator should be a static non-refcounted singleton on the stack really which would made the code much simpler, unfortunately its gtests rely on having the Shutdown method present to force re-scanning the devices and work with the mock cubeb.

Differential Revision: https://phabricator.services.mozilla.com/D82158
This commit is contained in:
Jean-Yves Avenard 2020-07-08 03:59:29 +00:00
Родитель bd343a92a2
Коммит a056adde5c
3 изменённых файлов: 22 добавлений и 12 удалений

Просмотреть файл

@ -6,9 +6,6 @@
#include "CubebUtils.h"
#ifdef MOZ_WEBRTC
# include "CubebDeviceEnumerator.h"
#endif
#include "MediaInfo.h"
#include "mozilla/AbstractThread.h"
#include "mozilla/dom/ContentChild.h"
@ -633,11 +630,6 @@ void ShutdownLibrary() {
Preferences::UnregisterCallbacks(PrefChanged, gInitCallbackPrefs);
Preferences::UnregisterCallbacks(PrefChanged, gCallbackPrefs);
#ifdef MOZ_WEBRTC
// This must be done before cubeb destroy.
CubebDeviceEnumerator::Shutdown();
#endif
StaticMutexAutoLock lock(sMutex);
if (sCubebContext) {
cubeb_destroy(sCubebContext);

Просмотреть файл

@ -6,7 +6,9 @@
#include "CubebDeviceEnumerator.h"
#include "mozilla/Atomics.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/SchedulerGroup.h"
#include "mozilla/StaticMutex.h"
#include "mozilla/StaticPtr.h"
#include "nsThreadUtils.h"
#ifdef XP_WIN
@ -18,12 +20,29 @@ namespace mozilla {
using namespace CubebUtils;
/* static */
StaticRefPtr<CubebDeviceEnumerator> CubebDeviceEnumerator::sInstance;
static StaticRefPtr<CubebDeviceEnumerator> sInstance;
static StaticMutex sInstanceMutex;
/* static */
CubebDeviceEnumerator* CubebDeviceEnumerator::GetInstance() {
StaticMutexAutoLock lock(sInstanceMutex);
if (!sInstance) {
sInstance = new CubebDeviceEnumerator();
static bool clearOnShutdownSetup = []() -> bool {
auto setClearOnShutdown = []() -> void {
ClearOnShutdown(&sInstance, ShutdownPhase::ShutdownThreads);
};
if (NS_IsMainThread()) {
setClearOnShutdown();
} else {
SchedulerGroup::Dispatch(
TaskCategory::Other,
NS_NewRunnableFunction("CubebDeviceEnumerator::::GetInstance()",
std::move(setClearOnShutdown)));
}
return true;
}();
Unused << clearOnShutdownSetup;
}
return sInstance.get();
}
@ -60,6 +79,7 @@ CubebDeviceEnumerator::CubebDeviceEnumerator()
/* static */
void CubebDeviceEnumerator::Shutdown() {
StaticMutexAutoLock lock(sInstanceMutex);
if (sInstance) {
sInstance = nullptr;
}

Просмотреть файл

@ -80,8 +80,6 @@ class CubebDeviceEnumerator final {
bool mManualOutputInvalidation;
MediaEventProducer<void> mOnInputDeviceListChange;
MediaEventProducer<void> mOnOutputDeviceListChange;
// The singleton instance.
static StaticRefPtr<CubebDeviceEnumerator> sInstance;
};
typedef CubebDeviceEnumerator Enumerator;