Bug 495794 - Fix crash when destroying audio stream that failed to open cleanly. r=chris.double
authorMatthew Gregan <kinetik@flim.org>
Thu, 02 Jul 2009 16:38:26 +1200
changeset 29958 e037975c9472063578d027ddffd7b0ca4a7302d9
parent 29957 231fe6f453d81b4caecf00ef8dd0478414559770
child 29959 0e868bb2de705709e4b15d41cdb544d292030e8d
push idunknown
push userunknown
push dateunknown
reviewerschris.double
bugs495794
milestone1.9.2a1pre
Bug 495794 - Fix crash when destroying audio stream that failed to open cleanly. r=chris.double
content/media/test/crashtests/495794-1.html
content/media/test/crashtests/495794-1.ogg
content/media/test/crashtests/crashtests.list
media/libsydneyaudio/README_MOZILLA
media/libsydneyaudio/bug495794_closeAudio.patch
media/libsydneyaudio/src/sydney_audio_waveapi.c
media/libsydneyaudio/update.sh
new file mode 100644
--- /dev/null
+++ b/content/media/test/crashtests/495794-1.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+  <body>
+    <audio src="495794-1.ogg" autoplay onended="document.documentElement.className=undefined"></audio>
+  </body>
+</html>
+
new file mode 100644
index 0000000000000000000000000000000000000000..1c19a640612dcfab2b3181f9f4da1d1247d11560
GIT binary patch
literal 4837
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
NzOyr<wKHSE{{yv@D+K@m
--- a/content/media/test/crashtests/crashtests.list
+++ b/content/media/test/crashtests/crashtests.list
@@ -1,2 +1,3 @@
 load 468763-1.html
 load 474744-1.html
+load 495794-1.html
--- a/media/libsydneyaudio/README_MOZILLA
+++ b/media/libsydneyaudio/README_MOZILLA
@@ -7,8 +7,11 @@ http://svn.annodex.net/libsydneyaudio/tr
 
 The svn revision number used was r3895.
 
 pause-resume.patch is applied to implement and fix issues
 with pausing and resuming audio streams.
 
 include-CoreServices.patch is applied to include CoreServices headers
 on Mac OS X. Fixes a build failure on Mac OS X 10.6. b=492072
+
+bug495794_closeAudio.patch fixes a crash when destroying the sa_stream_t after
+a failed attempt to open the stream.
new file mode 100644
--- /dev/null
+++ b/media/libsydneyaudio/bug495794_closeAudio.patch
@@ -0,0 +1,105 @@
+diff --git a/media/libsydneyaudio/src/sydney_audio_waveapi.c b/media/libsydneyaudio/src/sydney_audio_waveapi.c
+--- a/media/libsydneyaudio/src/sydney_audio_waveapi.c
++++ b/media/libsydneyaudio/src/sydney_audio_waveapi.c
+@@ -416,29 +416,34 @@ int openAudio(sa_stream_t *s) {
+   wfx.nBlockAlign		= (wfx.wBitsPerSample * wfx.nChannels) >> 3;
+   wfx.nAvgBytesPerSec	= wfx.nBlockAlign * wfx.nSamplesPerSec;
+ 
+   supported = waveOutOpen(NULL, WAVE_MAPPER, &wfx, (DWORD_PTR)0, (DWORD_PTR)0, 
+ 				WAVE_FORMAT_QUERY);
+   if (supported == MMSYSERR_NOERROR) { // audio device opened sucessfully 
+     status = waveOutOpen((LPHWAVEOUT)&(s->hWaveOut), WAVE_MAPPER, &wfx, 
+ 	  (DWORD_PTR)waveOutProc, (DWORD_PTR)s, CALLBACK_FUNCTION);
+-    HANDLE_WAVE_ERROR(status, "opening audio device for playback");
+-		printf("Audio device sucessfully opened\n");
++    if (status != MMSYSERR_NOERROR) {
++      freeBlocks(s->waveBlocks);
++      s->waveBlocks = NULL;
++      HANDLE_WAVE_ERROR(status, "opening audio device for playback");
++    }
+   } 
+   else if (supported == WAVERR_BADFORMAT) {
+-    printf("Requested format not supported...\n");
+-	  // clean up the memory
+-	  freeBlocks(s->waveBlocks);
++    printf("Requested format not supported.\n");
++    // clean up the memory
++    freeBlocks(s->waveBlocks);
++    s->waveBlocks = NULL;
+     return SA_ERROR_NOT_SUPPORTED;
+   } 
+   else {
+-    printf("Error opening default audio device. Exiting...\n");
+-	  // clean up the memory
+-	  freeBlocks(s->waveBlocks);
++    printf("Error opening default audio device.\n");
++    // clean up the memory
++    freeBlocks(s->waveBlocks);
++    s->waveBlocks = NULL;
+     return SA_ERROR_SYSTEM;
+   }
+   // create notification for data written to a device
+   s->callbackEvent = CreateEvent(0, FALSE, FALSE, 0);
+   // initialise critical section for operations on waveFreeBlockCound variable
+   InitializeCriticalSection(&(s->waveCriticalSection));
+ 
+   return SA_SUCCESS;
+@@ -454,40 +459,43 @@ int closeAudio(sa_stream_t * s) {
+   result = SA_SUCCESS;
+ 
+   // reseting audio device and flushing buffers
+   status = waveOutReset(s->hWaveOut);    
+   if (status != MMSYSERR_NOERROR) {
+     result = getSAErrorCode(status);
+   }
+   
+-  /* wait for all blocks to complete */  
+-  while(s->waveFreeBlockCount < BLOCK_COUNT) {
+-    Sleep(10);
++  if (s->waveBlocks) {
++    /* wait for all blocks to complete */  
++    while(s->waveFreeBlockCount < BLOCK_COUNT) {
++      Sleep(10);
++    }
++
++    /* unprepare any blocks that are still prepared */  
++    for(i = 0; i < s->waveFreeBlockCount; i++) {
++      if(s->waveBlocks[i].dwFlags & WHDR_PREPARED) {
++	status = waveOutUnprepareHeader(s->hWaveOut, &(s->waveBlocks[i]), sizeof(WAVEHDR));
++	if (status != MMSYSERR_NOERROR) {
++	  result = getSAErrorCode(status);
++	}
++      }
++    }    
++
++    freeBlocks(s->waveBlocks);  
++    s->waveBlocks = NULL;
+   }
+ 
+-  /* unprepare any blocks that are still prepared */  
+-  for(i = 0; i < s->waveFreeBlockCount; i++) {
+-    if(s->waveBlocks[i].dwFlags & WHDR_PREPARED) {
+-      status = waveOutUnprepareHeader(s->hWaveOut, &(s->waveBlocks[i]), sizeof(WAVEHDR));
+-      if (status != MMSYSERR_NOERROR) {
+-        result = getSAErrorCode(status);
+-      }
+-    }
+-  }    
+-
+-  freeBlocks(s->waveBlocks);  
+   status = waveOutClose(s->hWaveOut);    
+   if (status != MMSYSERR_NOERROR) {
+     result = getSAErrorCode(status);
+   }
+ 
+   DeleteCriticalSection(&(s->waveCriticalSection));
+   CloseHandle(s->callbackEvent);
+-  printf("[audio] audio resources cleanup completed\n");
+   
+   return result;
+ }
+ /**
+  * \brief - writes PCM audio samples to audio device
+  * \param s - valid handle to opened sydney stream
+  * \param data - pointer to memory storing audio samples to be played
+  * \param nsamples - number of samples in the memory pointed by previous parameter
--- a/media/libsydneyaudio/src/sydney_audio_waveapi.c
+++ b/media/libsydneyaudio/src/sydney_audio_waveapi.c
@@ -416,29 +416,34 @@ int openAudio(sa_stream_t *s) {
   wfx.nBlockAlign		= (wfx.wBitsPerSample * wfx.nChannels) >> 3;
   wfx.nAvgBytesPerSec	= wfx.nBlockAlign * wfx.nSamplesPerSec;
 
   supported = waveOutOpen(NULL, WAVE_MAPPER, &wfx, (DWORD_PTR)0, (DWORD_PTR)0, 
 				WAVE_FORMAT_QUERY);
   if (supported == MMSYSERR_NOERROR) { // audio device opened sucessfully 
     status = waveOutOpen((LPHWAVEOUT)&(s->hWaveOut), WAVE_MAPPER, &wfx, 
 	  (DWORD_PTR)waveOutProc, (DWORD_PTR)s, CALLBACK_FUNCTION);
-    HANDLE_WAVE_ERROR(status, "opening audio device for playback");
-		printf("Audio device sucessfully opened\n");
+    if (status != MMSYSERR_NOERROR) {
+      freeBlocks(s->waveBlocks);
+      s->waveBlocks = NULL;
+      HANDLE_WAVE_ERROR(status, "opening audio device for playback");
+    }
   } 
   else if (supported == WAVERR_BADFORMAT) {
-    printf("Requested format not supported...\n");
-	  // clean up the memory
-	  freeBlocks(s->waveBlocks);
+    printf("Requested format not supported.\n");
+    // clean up the memory
+    freeBlocks(s->waveBlocks);
+    s->waveBlocks = NULL;
     return SA_ERROR_NOT_SUPPORTED;
   } 
   else {
-    printf("Error opening default audio device. Exiting...\n");
-	  // clean up the memory
-	  freeBlocks(s->waveBlocks);
+    printf("Error opening default audio device.\n");
+    // clean up the memory
+    freeBlocks(s->waveBlocks);
+    s->waveBlocks = NULL;
     return SA_ERROR_SYSTEM;
   }
   // create notification for data written to a device
   s->callbackEvent = CreateEvent(0, FALSE, FALSE, 0);
   // initialise critical section for operations on waveFreeBlockCound variable
   InitializeCriticalSection(&(s->waveCriticalSection));
 
   return SA_SUCCESS;
@@ -454,40 +459,43 @@ int closeAudio(sa_stream_t * s) {
   result = SA_SUCCESS;
 
   // reseting audio device and flushing buffers
   status = waveOutReset(s->hWaveOut);    
   if (status != MMSYSERR_NOERROR) {
     result = getSAErrorCode(status);
   }
   
-  /* wait for all blocks to complete */  
-  while(s->waveFreeBlockCount < BLOCK_COUNT) {
-    Sleep(10);
+  if (s->waveBlocks) {
+    /* wait for all blocks to complete */  
+    while(s->waveFreeBlockCount < BLOCK_COUNT) {
+      Sleep(10);
+    }
+
+    /* unprepare any blocks that are still prepared */  
+    for(i = 0; i < s->waveFreeBlockCount; i++) {
+      if(s->waveBlocks[i].dwFlags & WHDR_PREPARED) {
+	status = waveOutUnprepareHeader(s->hWaveOut, &(s->waveBlocks[i]), sizeof(WAVEHDR));
+	if (status != MMSYSERR_NOERROR) {
+	  result = getSAErrorCode(status);
+	}
+      }
+    }    
+
+    freeBlocks(s->waveBlocks);  
+    s->waveBlocks = NULL;
   }
 
-  /* unprepare any blocks that are still prepared */  
-  for(i = 0; i < s->waveFreeBlockCount; i++) {
-    if(s->waveBlocks[i].dwFlags & WHDR_PREPARED) {
-      status = waveOutUnprepareHeader(s->hWaveOut, &(s->waveBlocks[i]), sizeof(WAVEHDR));
-      if (status != MMSYSERR_NOERROR) {
-        result = getSAErrorCode(status);
-      }
-    }
-  }    
-
-  freeBlocks(s->waveBlocks);  
   status = waveOutClose(s->hWaveOut);    
   if (status != MMSYSERR_NOERROR) {
     result = getSAErrorCode(status);
   }
 
   DeleteCriticalSection(&(s->waveCriticalSection));
   CloseHandle(s->callbackEvent);
-  printf("[audio] audio resources cleanup completed\n");
   
   return result;
 }
 /**
  * \brief - writes PCM audio samples to audio device
  * \param s - valid handle to opened sydney stream
  * \param data - pointer to memory storing audio samples to be played
  * \param nsamples - number of samples in the memory pointed by previous parameter
--- a/media/libsydneyaudio/update.sh
+++ b/media/libsydneyaudio/update.sh
@@ -2,8 +2,9 @@
 #
 # Copies the needed files from a directory containing the original
 # liboggplay source that we need for the Mozilla HTML5 media support.
 cp $1/include/sydney_audio.h include/sydney_audio.h
 cp $1/src/*.c src/
 cp $1/AUTHORS ./AUTHORS
 patch -p4 <pause-resume.patch
 patch -p4 <include-CoreServices.patch
+patch -p3 <bug495794_closeAudio.patch