Skip to content

Commit f0b04ce

Browse files
committed
Avoid forming deadlock when steam drains upon device switching
This solves the deadlock mentioned in BMO 1572273 comment 6. It's very likely to have a deadlock when the output callback tries to stop the input AudioUnit when the input device is unplugged during the duplex stream is working. When the input device is unplugged, the stream will be reinitialized and the AudioUnits will be stopped then. Hence we could only feed silence to the output buffer and let stream reinit stop the AudioUnits.
1 parent 0b5b52d commit f0b04ce

1 file changed

Lines changed: 12 additions & 5 deletions

File tree

src/cubeb_audiounit.cpp

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -612,13 +612,20 @@ audiounit_output_callback(void * user_ptr,
612612
}
613613

614614
if (stm->draining) {
615-
OSStatus r = AudioOutputUnitStop(stm->output_unit);
616-
assert(r == 0);
617-
if (stm->input_unit) {
618-
r = AudioOutputUnitStop(stm->input_unit);
615+
if (stm->reinit_pending) {
616+
ALOG("(%p) stream is reinitializing.", stm);
617+
// The stream reinit will stop the AudioUnits anyway.
618+
} else {
619+
ALOG("(%p) stop the AudioUnits.", stm);
620+
OSStatus r = AudioOutputUnitStop(stm->output_unit);
619621
assert(r == 0);
622+
if (stm->input_unit) {
623+
r = AudioOutputUnitStop(stm->input_unit);
624+
assert(r == 0);
625+
}
626+
stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_DRAINED);
620627
}
621-
stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_DRAINED);
628+
ALOG("(%p) stream is draining. feed silence.", stm);
622629
audiounit_make_silent(&outBufferList->mBuffers[0]);
623630
return noErr;
624631
}

0 commit comments

Comments
 (0)