Skip to content

Commit 4a8c9b8

Browse files
authored
Fix infinite loop on broken ALSA pipes (#934)
1 parent c11571b commit 4a8c9b8

File tree

1 file changed

+13
-0
lines changed

1 file changed

+13
-0
lines changed

src/host/alsa/mod.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use crate::{
1010
SupportedBufferSize, SupportedStreamConfig, SupportedStreamConfigRange,
1111
SupportedStreamConfigsError,
1212
};
13+
use std::cell::Cell;
1314
use std::cmp;
1415
use std::convert::TryInto;
1516
use std::sync::{Arc, Mutex};
@@ -286,6 +287,7 @@ impl Device {
286287
}
287288

288289
let stream_inner = StreamInner {
290+
dropping: Cell::new(false),
289291
channel: handle,
290292
sample_format,
291293
num_descriptors,
@@ -501,6 +503,10 @@ impl Device {
501503
}
502504

503505
struct StreamInner {
506+
// Flag used to check when to stop polling, regardless of the state of the stream
507+
// (e.g. broken due to a disconnected device).
508+
dropping: Cell<bool>,
509+
504510
// The ALSA channel.
505511
channel: alsa::pcm::PCM,
506512

@@ -696,6 +702,12 @@ fn poll_descriptors_and_prepare_buffer(
696702
stream: &StreamInner,
697703
ctxt: &mut StreamWorkerContext,
698704
) -> Result<PollDescriptorsFlow, BackendSpecificError> {
705+
if stream.dropping.get() {
706+
// The stream has been requested to be destroyed.
707+
rx.clear_pipe();
708+
return Ok(PollDescriptorsFlow::Return);
709+
}
710+
699711
let StreamWorkerContext {
700712
ref mut descriptors,
701713
ref mut buffer,
@@ -982,6 +994,7 @@ impl Stream {
982994

983995
impl Drop for Stream {
984996
fn drop(&mut self) {
997+
self.inner.dropping.set(true);
985998
self.trigger.wakeup();
986999
self.thread.take().unwrap().join().unwrap();
9871000
}

0 commit comments

Comments
 (0)