Potential fix for crash after Mac sleep.

When a Mac goes to sleep, the OS pauses the IO threads. If a
subsequent StopSend/Playout happens, we time out waiting for the IO
threads, but didn't ensure they were shut down.

BUG=
TEST=voe_cmd_test, voe_auto_test

Review URL: http://webrtc-codereview.appspot.com/269013

git-svn-id: http://webrtc.googlecode.com/svn/trunk@949 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
andrew@webrtc.org 2011-11-15 16:23:41 +00:00
parent 85596d5bf4
commit 6a85b17a0a

View File

@ -1999,9 +1999,16 @@ WebRtc_Word32 AudioDeviceMac::StopRecording()
_critSect.Leave(); // Cannot be under lock, risk of deadlock _critSect.Leave(); // Cannot be under lock, risk of deadlock
if (kEventTimeout == _stopEventRec.Wait(2000)) if (kEventTimeout == _stopEventRec.Wait(2000))
{ {
WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, CriticalSectionScoped critScoped(_critSect);
_id, " Timed out stopping the capture IOProc. " WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
"We likely failed to detect a device removal."); " Timed out stopping the capture IOProc. "
"We may have failed to detect a device removal.");
WEBRTC_CA_LOG_WARN(AudioDeviceStop(_inputDeviceID,
_inDeviceIOProcID));
WEBRTC_CA_LOG_WARN(
AudioDeviceDestroyIOProcID(_inputDeviceID,
_inDeviceIOProcID));
} }
_critSect.Enter(); _critSect.Enter();
_doStopRec = false; _doStopRec = false;
@ -2025,9 +2032,17 @@ WebRtc_Word32 AudioDeviceMac::StopRecording()
_critSect.Leave(); // Cannot be under lock, risk of deadlock _critSect.Leave(); // Cannot be under lock, risk of deadlock
if (kEventTimeout == _stopEvent.Wait(2000)) if (kEventTimeout == _stopEvent.Wait(2000))
{ {
WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, CriticalSectionScoped critScoped(_critSect);
_id, " Timed out stopping the shared IOProc. " WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
"We likely failed to detect a device removal."); " Timed out stopping the shared IOProc. "
"We may have failed to detect a device removal.");
// We assume rendering on a shared device has stopped as well if
// the IOProc times out.
WEBRTC_CA_LOG_WARN(AudioDeviceStop(_outputDeviceID,
_deviceIOProcID));
WEBRTC_CA_LOG_WARN(AudioDeviceDestroyIOProcID(_outputDeviceID,
_deviceIOProcID));
} }
_critSect.Enter(); _critSect.Enter();
_doStop = false; _doStop = false;
@ -2165,15 +2180,22 @@ WebRtc_Word32 AudioDeviceMac::StopPlayout()
_critSect.Leave(); // Cannot be under lock, risk of deadlock _critSect.Leave(); // Cannot be under lock, risk of deadlock
if (kEventTimeout == _stopEvent.Wait(2000)) if (kEventTimeout == _stopEvent.Wait(2000))
{ {
WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, CriticalSectionScoped critScoped(_critSect);
"Timed out stopping the render IOProc, " WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
"We likely failed to detect a device removal."); " Timed out stopping the render IOProc. "
"We may have failed to detect a device removal.");
// We assume capturing on a shared device has stopped as well if the
// IOProc times out.
WEBRTC_CA_LOG_WARN(AudioDeviceStop(_outputDeviceID,
_deviceIOProcID));
WEBRTC_CA_LOG_WARN(AudioDeviceDestroyIOProcID(_outputDeviceID,
_deviceIOProcID));
} }
_critSect.Enter(); _critSect.Enter();
_doStop = false; _doStop = false;
WEBRTC_TRACE(kTraceDebug, kTraceAudioDevice, _id, WEBRTC_TRACE(kTraceDebug, kTraceAudioDevice, _id,
"Playout stopped"); "Playout stopped");
} }
// Setting this signal will allow the worker thread to be stopped. // Setting this signal will allow the worker thread to be stopped.
@ -2185,7 +2207,7 @@ WebRtc_Word32 AudioDeviceMac::StopPlayout()
{ {
WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
" Timed out waiting for the render worker thread to " " Timed out waiting for the render worker thread to "
"stop."); "stop.");
} }
} }
_critSect.Enter(); _critSect.Enter();
@ -3026,7 +3048,6 @@ OSStatus AudioDeviceMac::implDeviceIOProc(const AudioBufferList *inputData,
{ {
WEBRTC_CA_LOG_ERR(AudioDeviceStop(_outputDeviceID, WEBRTC_CA_LOG_ERR(AudioDeviceStop(_outputDeviceID,
_deviceIOProcID)); _deviceIOProcID));
WEBRTC_CA_LOG_WARN(AudioDeviceDestroyIOProcID(_outputDeviceID, WEBRTC_CA_LOG_WARN(AudioDeviceDestroyIOProcID(_outputDeviceID,
_deviceIOProcID)); _deviceIOProcID));
} }
@ -3035,10 +3056,8 @@ OSStatus AudioDeviceMac::implDeviceIOProc(const AudioBufferList *inputData,
#endif #endif
WEBRTC_CA_LOG_ERR(AudioDeviceStop(_outputDeviceID, WEBRTC_CA_LOG_ERR(AudioDeviceStop(_outputDeviceID,
deviceIOProc)); deviceIOProc));
WEBRTC_CA_LOG_WARN(AudioDeviceRemoveIOProc(_outputDeviceID, WEBRTC_CA_LOG_WARN(AudioDeviceRemoveIOProc(_outputDeviceID,
deviceIOProc)); deviceIOProc));
#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1050 #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
} }
#endif #endif
@ -3149,7 +3168,6 @@ OSStatus AudioDeviceMac::implInDeviceIOProc(const AudioBufferList *inputData,
if (AudioDeviceCreateIOProcID != NULL) if (AudioDeviceCreateIOProcID != NULL)
{ {
WEBRTC_CA_LOG_ERR(AudioDeviceStop(_inputDeviceID, _inDeviceIOProcID)); WEBRTC_CA_LOG_ERR(AudioDeviceStop(_inputDeviceID, _inDeviceIOProcID));
WEBRTC_CA_LOG_WARN(AudioDeviceDestroyIOProcID(_inputDeviceID, WEBRTC_CA_LOG_WARN(AudioDeviceDestroyIOProcID(_inputDeviceID,
_inDeviceIOProcID)); _inDeviceIOProcID));
} }
@ -3157,7 +3175,6 @@ OSStatus AudioDeviceMac::implInDeviceIOProc(const AudioBufferList *inputData,
{ {
#endif #endif
WEBRTC_CA_LOG_ERR(AudioDeviceStop(_inputDeviceID, inDeviceIOProc)); WEBRTC_CA_LOG_ERR(AudioDeviceStop(_inputDeviceID, inDeviceIOProc));
WEBRTC_CA_LOG_WARN(AudioDeviceRemoveIOProc(_inputDeviceID, WEBRTC_CA_LOG_WARN(AudioDeviceRemoveIOProc(_inputDeviceID,
inDeviceIOProc)); inDeviceIOProc));
#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1050 #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1050