Input & Driver: Fix zombie processes on Unix (#39)

Linux/Unix requires that processes be waited, which is unfortunate as Windows lets us abandon them to the murderous whims of the OS. This PR adds Unix-specific behaviour to send a SIGINT before waiting on the process, and adds an additional thread per call for asset disposal on all platforms.

Closes #38.

---

* Close processes by SIGINT and wait on Unix

This seems to remedy the Linux-specific zombie processes. Addition of
nix as a dependency *should* be fine on Windows, since I believe it
compiles to an empty crate.

* Dispose of Tracks on auxiliary thread

This adds a mechanism for the mixer threads to perform potentially expensive deallocation/cleanup outside of the main loop, preventing deadline misses etc. This should make misbehaving `wait`s a bit more friendly.
This commit is contained in:
Kyle Simpson
2021-01-26 20:19:51 +00:00
committed by GitHub
parent a0e905a83f
commit fe2282cfde
7 changed files with 64 additions and 4 deletions

View File

@@ -1,4 +1,4 @@
use super::{error::Result, message::*, Config};
use super::{disposal, error::Result, message::*, Config};
use crate::{
constants::*,
tracks::{PlayMode, Track},
@@ -28,6 +28,7 @@ pub struct Mixer {
pub config: Config,
pub conn_active: Option<MixerConnection>,
pub deadline: Instant,
pub disposer: Sender<DisposalMessage>,
pub encoder: OpusEncoder,
pub interconnect: Interconnect,
pub mix_rx: Receiver<MixerMessage>,
@@ -74,12 +75,17 @@ impl Mixer {
let tracks = Vec::with_capacity(1.max(config.preallocated_tracks));
// Create an object disposal thread here.
let (disposer, disposal_rx) = flume::unbounded();
std::thread::spawn(move || disposal::runner(disposal_rx));
Self {
async_handle,
bitrate,
config,
conn_active: None,
deadline: Instant::now(),
disposer,
encoder,
interconnect,
mix_rx,
@@ -322,12 +328,13 @@ impl Mixer {
if track.playing.is_done() {
let p_state = track.playing();
self.tracks.swap_remove(i);
let to_drop = self.tracks.swap_remove(i);
to_remove.push(i);
self.fire_event(EventMessage::ChangeState(
i,
TrackStateChange::Mode(p_state),
))?;
let _ = self.disposer.send(DisposalMessage::Track(to_drop));
} else {
i += 1;
}
@@ -580,4 +587,6 @@ pub(crate) fn runner(
let mut mixer = Mixer::new(mix_rx, async_handle, interconnect, config);
mixer.run();
let _ = mixer.disposer.send(DisposalMessage::Poison);
}