Skip to content

Commit

Permalink
Break reference cycle in voice storage example (#44)
Browse files Browse the repository at this point in the history
Changes a stored `Arc` pointer to the call (used to queue up further tracks in response to events) into a `Weak`, as the event handler's strong pointer would keep the Call and Driver objects alive. This would have caused an unintentional resource leak of threads/tasks. This was found by some internal profiling in search of #42.
  • Loading branch information
FelixMcFelix authored Mar 11, 2021
1 parent dd49c5d commit b9a926c
Showing 1 changed file with 13 additions and 11 deletions.
24 changes: 13 additions & 11 deletions examples/serenity/voice_storage/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
//! git = "https://github.com/serenity-rs/serenity.git"
//! features = ["cache", "framework", "standard_framework", "voice"]
//! ```
use std::{collections::HashMap, convert::TryInto, env, sync::Arc};
use std::{collections::HashMap, convert::TryInto, env, sync::{Arc, Weak}};

use serenity::{
async_trait,
Expand Down Expand Up @@ -206,7 +206,7 @@ async fn join(ctx: &Context, msg: &Message) -> CommandResult {

let (handler_lock, success_reader) = manager.join(guild_id, connect_to).await;

let call_lock_for_evt = handler_lock.clone();
let call_lock_for_evt = Arc::downgrade(&handler_lock);

if let Ok(_reader) = success_reader {
let mut handler = handler_lock.lock().await;
Expand Down Expand Up @@ -237,21 +237,23 @@ async fn join(ctx: &Context, msg: &Message) -> CommandResult {
}

struct LoopPlaySound {
call_lock: Arc<Mutex<Call>>,
call_lock: Weak<Mutex<Call>>,
sources: Arc<Mutex<HashMap<String, CachedSound>>>,
}

#[async_trait]
impl VoiceEventHandler for LoopPlaySound {
async fn act(&self, _ctx: &EventContext<'_>) -> Option<Event> {
let src = {
let sources = self.sources.lock().await;
sources.get("loop").expect("Handle placed into cache at startup.").into()
};

let mut handler = self.call_lock.lock().await;
let sound = handler.play_source(src);
let _ = sound.set_volume(0.5);
if let Some(call_lock) = self.call_lock.upgrade() {
let src = {
let sources = self.sources.lock().await;
sources.get("loop").expect("Handle placed into cache at startup.").into()
};

let mut handler = call_lock.lock().await;
let sound = handler.play_source(src);
let _ = sound.set_volume(0.5);
}

None
}
Expand Down

0 comments on commit b9a926c

Please sign in to comment.