Bug 714078: Don't do anything risking a deadlock in IAudioSessionEvents callbacks. r=ehsan
authorKyle Huey <khuey@kylehuey.com>
Thu, 29 Dec 2011 11:59:29 -0500
changeset 84740 ef6d44e6087546920da248d9d369f143082709b0
parent 84739 cff462dee8f7b7ddd372593567e8d17005c667f9
child 84741 972982711eb315c39a18a111d4109dfea03fcd84
push id805
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 18:17:35 +0000
treeherdermozilla-aurora@6fb3bf232436 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersehsan
bugs714078
milestone12.0a1
Bug 714078: Don't do anything risking a deadlock in IAudioSessionEvents callbacks. r=ehsan
widget/src/windows/AudioSession.cpp
--- a/widget/src/windows/AudioSession.cpp
+++ b/widget/src/windows/AudioSession.cpp
@@ -46,16 +46,17 @@
 #include "nsIUUIDGenerator.h"
 #include "nsIXULAppInfo.h"
 
 //#include "AudioSession.h"
 #include "nsCOMPtr.h"
 #include "nsAutoPtr.h"
 #include "nsServiceManagerUtils.h"
 #include "nsString.h"
+#include "nsThreadUtils.h"
 #include "nsXULAppAPI.h"
 
 #include <objbase.h>
 
 namespace mozilla {
 namespace widget {
 
 /* 
@@ -79,16 +80,19 @@ public:
   STDMETHODIMP OnChannelVolumeChanged(DWORD aChannelCount,
                                       float aChannelVolumeArray[],
                                       DWORD aChangedChannel,
                                       LPCGUID aContext);
   STDMETHODIMP OnDisplayNameChanged(LPCWSTR aDisplayName, LPCGUID aContext);
   STDMETHODIMP OnGroupingParamChanged(LPCGUID aGroupingParam, LPCGUID aContext);
   STDMETHODIMP OnIconPathChanged(LPCWSTR aIconPath, LPCGUID aContext);
   STDMETHODIMP OnSessionDisconnected(AudioSessionDisconnectReason aReason);
+private:
+  nsresult OnSessionDisconnectedInternal();
+public:
   STDMETHODIMP OnSimpleVolumeChanged(float aVolume,
                                      BOOL aMute,
                                      LPCGUID aContext);
   STDMETHODIMP OnStateChanged(AudioSessionState aState);
 
   nsresult Start();
   nsresult Stop();
   void StopInternal();
@@ -427,23 +431,35 @@ AudioSession::OnIconPathChanged(LPCWSTR 
                                 LPCGUID aContext)
 {
   return S_OK; // NOOP
 }
 
 STDMETHODIMP
 AudioSession::OnSessionDisconnected(AudioSessionDisconnectReason aReason)
 {
+  // Run our code asynchronously.  Per MSDN we can't do anything interesting
+  // in this callback.
+  nsCOMPtr<nsIRunnable> runnable =
+    NS_NewRunnableMethod(this, &AudioSession::OnSessionDisconnectedInternal);
+  NS_DispatchToMainThread(runnable);
+  return S_OK;
+}
+
+nsresult
+AudioSession::OnSessionDisconnectedInternal()
+{
   if (!mAudioSessionControl)
-    return S_OK;
+    return NS_OK;
 
   mAudioSessionControl->UnregisterAudioSessionNotification(this);
   mAudioSessionControl = nsnull;
-  Start(); // If it fails there's not much we can do
-  return S_OK;
+
+  Start(); // If it fails there's not much we can do.
+  return NS_OK;
 }
 
 STDMETHODIMP
 AudioSession::OnSimpleVolumeChanged(float aVolume,
                                     BOOL aMute,
                                     LPCGUID aContext)
 {
   return S_OK; // NOOP