Skip to content

Commit 4fefac3

Browse files
Qiumixfaervan
authored andcommitted
fix: kill subscription child processes on drop
pactl subscribe (volume) and playerctl --follow (media) child processes were never terminated when their subscription ended, leaking one orphan per reload and eventually exhausting the pulse client limit.
1 parent ea2711a commit 4fefac3

3 files changed

Lines changed: 21 additions & 2 deletions

File tree

src/modules/media.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use crate::{
2727
};
2828
use crate::{impl_on_click, impl_wrapper};
2929

30-
use super::Module;
30+
use super::{KillOnDrop, Module};
3131

3232
#[derive(Debug, Builder)]
3333
pub struct MediaMod {
@@ -493,6 +493,10 @@ impl Module for MediaMod {
493493
.take()
494494
.expect("child did not have a handle to stdout");
495495

496+
// Kill playerctl when the subscription ends (e.g. on reload),
497+
// so it doesn't leak and accumulate processes.
498+
let _kill_on_drop = KillOnDrop(child);
499+
496500
let mut reader = BufReader::new(stdout).lines();
497501
let mut last_track = String::new();
498502

src/modules/mod.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,17 @@ pub trait Module: Any + Debug + Send + Sync + Downcast {
160160
}
161161
impl_downcast!(Module);
162162

163+
/// Kills the wrapped child process when dropped, so subscription child
164+
/// processes (e.g. `pactl subscribe`, `playerctl --follow`) don't leak when
165+
/// the subscription ends (e.g. on config reload).
166+
pub struct KillOnDrop(pub tokio::process::Child);
167+
168+
impl Drop for KillOnDrop {
169+
fn drop(&mut self) {
170+
let _ = self.0.start_kill();
171+
}
172+
}
173+
163174
pub trait Action: Any + Debug + Send + Sync + Downcast {
164175
fn as_message(&self) -> Message;
165176
}

src/modules/volume.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use crate::{
2121
};
2222
use crate::{impl_on_click, impl_wrapper};
2323

24-
use super::Module;
24+
use super::{KillOnDrop, Module};
2525

2626
#[derive(Default, Debug, Builder)]
2727
pub struct VolumeMod {
@@ -109,6 +109,10 @@ impl Module for VolumeMod {
109109
.take()
110110
.expect("child did not have a handle to stdout");
111111

112+
// Kill pactl when the subscription ends (e.g. on reload), so
113+
// it doesn't leak and exhaust the pulse client limit.
114+
let _kill_on_drop = KillOnDrop(child);
115+
112116
let mut reader = BufReader::new(stdout).lines();
113117

114118
while let Some(line) = reader.next_line().await.unwrap() {

0 commit comments

Comments
 (0)