Bug 1412394 - Delay blocking MediaManager::PostTask until media thread shutdown. r=jib

This delays setting sInShutdown (renamed to sHasShutdown for better semantics)
until all that remains of shutdown is to shut down the media thread.

From JS this is no change as JS cannot run until Shutdown() is done.

The difference is that we let members and still-active listeners get destroyed
and cause any members that are media-thread only (in this case devices), to shut
down before the thread goes away.

MozReview-Commit-ID: 5NTWwh8Umn8

--HG--
extra : rebase_source : f6b508abc95434f027a6544fdac53949138764da
This commit is contained in:
Andreas Pehrson 2017-11-02 16:27:33 +01:00
Родитель 868d1f83f6
Коммит 5b49365cb5
1 изменённых файлов: 16 добавлений и 13 удалений

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

@ -148,7 +148,7 @@ using media::NewTaskFrom;
using media::Pledge; using media::Pledge;
using media::Refcountable; using media::Refcountable;
static Atomic<bool> sInShutdown; static Atomic<bool> sHasShutdown;
typedef media::Pledge<bool, dom::MediaStreamError*> PledgeVoid; typedef media::Pledge<bool, dom::MediaStreamError*> PledgeVoid;
@ -1095,7 +1095,7 @@ public:
const MediaTrackConstraints& aConstraints, const MediaTrackConstraints& aConstraints,
dom::CallerType aCallerType) override dom::CallerType aCallerType) override
{ {
if (sInShutdown || !mListener) { if (sHasShutdown || !mListener) {
// Track has been stopped, or we are in shutdown. In either case // Track has been stopped, or we are in shutdown. In either case
// there's no observable outcome, so pretend we succeeded. // there's no observable outcome, so pretend we succeeded.
RefPtr<PledgeVoid> p = new PledgeVoid(); RefPtr<PledgeVoid> p = new PledgeVoid();
@ -1176,14 +1176,14 @@ public:
} }
} }
if (!domStream || !stream || sInShutdown) { if (!domStream || !stream || sHasShutdown) {
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onFailure = mOnFailure.forget(); nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onFailure = mOnFailure.forget();
LOG(("Returning error for getUserMedia() - no stream")); LOG(("Returning error for getUserMedia() - no stream"));
if (auto* window = nsGlobalWindowInner::GetInnerWindowWithId(mWindowID)) { if (auto* window = nsGlobalWindowInner::GetInnerWindowWithId(mWindowID)) {
RefPtr<MediaStreamError> error = new MediaStreamError(window->AsInner(), RefPtr<MediaStreamError> error = new MediaStreamError(window->AsInner(),
NS_LITERAL_STRING("InternalError"), NS_LITERAL_STRING("InternalError"),
sInShutdown ? NS_LITERAL_STRING("In shutdown") : sHasShutdown ? NS_LITERAL_STRING("In shutdown") :
NS_LITERAL_STRING("No stream.")); NS_LITERAL_STRING("No stream."));
onFailure->OnError(error); onFailure->OnError(error);
} }
@ -1978,7 +1978,7 @@ MediaManager::StartupInit()
void void
MediaManager::PostTask(already_AddRefed<Runnable> task) MediaManager::PostTask(already_AddRefed<Runnable> task)
{ {
if (sInShutdown) { if (sHasShutdown) {
// Can't safely delete task here since it may have items with specific // Can't safely delete task here since it may have items with specific
// thread-release requirements. // thread-release requirements.
// XXXkhuey well then who is supposed to delete it?! We don't signal // XXXkhuey well then who is supposed to delete it?! We don't signal
@ -2055,7 +2055,7 @@ void MediaManager::OnDeviceChange() {
RefPtr<MediaManager> self(this); RefPtr<MediaManager> self(this);
NS_DispatchToMainThread(media::NewRunnableFrom([self]() mutable { NS_DispatchToMainThread(media::NewRunnableFrom([self]() mutable {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
if (sInShutdown) { if (sHasShutdown) {
return NS_OK; return NS_OK;
} }
self->DeviceChangeCallback::OnDeviceChange(); self->DeviceChangeCallback::OnDeviceChange();
@ -2218,7 +2218,7 @@ MediaManager::GetUserMedia(nsPIDOMWindowInner* aWindow,
return NS_OK; return NS_OK;
} }
if (sInShutdown) { if (sHasShutdown) {
RefPtr<MediaStreamError> error = RefPtr<MediaStreamError> error =
new MediaStreamError(aWindow, new MediaStreamError(aWindow,
NS_LITERAL_STRING("AbortError"), NS_LITERAL_STRING("AbortError"),
@ -2816,7 +2816,7 @@ MediaManager::EnumerateDevices(nsPIDOMWindowInner* aWindow,
dom::CallerType aCallerType) dom::CallerType aCallerType)
{ {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
NS_ENSURE_TRUE(!sInShutdown, NS_ERROR_FAILURE); NS_ENSURE_TRUE(!sHasShutdown, NS_ERROR_FAILURE);
nsCOMPtr<nsIGetUserMediaDevicesSuccessCallback> onSuccess(aOnSuccess); nsCOMPtr<nsIGetUserMediaDevicesSuccessCallback> onSuccess(aOnSuccess);
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onFailure(aOnFailure); nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onFailure(aOnFailure);
uint64_t windowId = aWindow->WindowID(); uint64_t windowId = aWindow->WindowID();
@ -2908,7 +2908,7 @@ MediaManager::GetBackend(uint64_t aWindowId)
// includes picture support for Android. // includes picture support for Android.
// This IS called off main-thread. // This IS called off main-thread.
if (!mBackend) { if (!mBackend) {
MOZ_RELEASE_ASSERT(!sInShutdown); // we should never create a new backend in shutdown MOZ_RELEASE_ASSERT(!sHasShutdown); // we should never create a new backend in shutdown
#if defined(MOZ_WEBRTC) #if defined(MOZ_WEBRTC)
mBackend = new MediaEngineWebRTC(mPrefs); mBackend = new MediaEngineWebRTC(mPrefs);
#else #else
@ -3086,10 +3086,9 @@ void
MediaManager::Shutdown() MediaManager::Shutdown()
{ {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
if (sInShutdown) { if (sHasShutdown) {
return; return;
} }
sInShutdown = true;
nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
@ -3128,6 +3127,10 @@ MediaManager::Shutdown()
StopWebRtcLog(); StopWebRtcLog();
#endif #endif
// From main thread's point of view, shutdown is now done.
// All that remains is shutting down the media thread.
sHasShutdown = true;
// Because mMediaThread is not an nsThread, we must dispatch to it so it can // Because mMediaThread is not an nsThread, we must dispatch to it so it can
// clean up BackgroundChild. Continue stopping thread once this is done. // clean up BackgroundChild. Continue stopping thread once this is done.
@ -3180,7 +3183,7 @@ MediaManager::Shutdown()
RefPtr<MediaManager> that = this; RefPtr<MediaManager> that = this;
// Release the backend (and call Shutdown()) from within the MediaManager thread // Release the backend (and call Shutdown()) from within the MediaManager thread
// Don't use MediaManager::PostTask() because we're sInShutdown=true here! // Don't use MediaManager::PostTask() because we're sHasShutdown=true here!
RefPtr<ShutdownTask> shutdown = new ShutdownTask(this, RefPtr<ShutdownTask> shutdown = new ShutdownTask(this,
media::NewRunnableFrom([this, that]() mutable { media::NewRunnableFrom([this, that]() mutable {
LOG(("MediaManager shutdown lambda running, releasing MediaManager singleton and thread")); LOG(("MediaManager shutdown lambda running, releasing MediaManager singleton and thread"));
@ -3291,7 +3294,7 @@ MediaManager::Observe(nsISupports* aSubject, const char* aTopic,
} }
} }
if (sInShutdown) { if (sHasShutdown) {
return task->Denied(NS_LITERAL_STRING("In shutdown")); return task->Denied(NS_LITERAL_STRING("In shutdown"));
} }
// Reuse the same thread to save memory. // Reuse the same thread to save memory.