From 7eb362e8bc26cf8d9c16b57959c4b8690cd2f345 Mon Sep 17 00:00:00 2001 From: trivernis Date: Thu, 22 Apr 2021 12:34:40 +0200 Subject: [PATCH] Wrap event execution in tokio::spawn to avoid deadlocks Signed-off-by: trivernis --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/events/handler.rs | 99 +++++++++++++++++++++++-------------------- 3 files changed, 54 insertions(+), 49 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c4c0772..a767e86 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1033,7 +1033,7 @@ dependencies = [ [[package]] name = "serenity-rich-interaction" -version = "0.2.0" +version = "0.2.1" dependencies = [ "futures", "log", diff --git a/Cargo.toml b/Cargo.toml index a5875be..a46c2b8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serenity-rich-interaction" -version = "0.2.0" +version = "0.2.1" authors = ["trivernis "] edition = "2018" description = "Menus and self deleting messages for the serenity discord framework" diff --git a/src/events/handler.rs b/src/events/handler.rs index 278d021..996811d 100644 --- a/src/events/handler.rs +++ b/src/events/handler.rs @@ -43,21 +43,26 @@ impl EventCallback { /// // ... /// ``` pub struct RichEventHandler { - callbacks: HashMap>>, + callbacks: HashMap>>, } impl RichEventHandler { /// Handles a generic event - async fn handle_event(&self, ctx: &Context, value: T) { - if let Some(callbacks) = self.callbacks.get(&TypeId::of::()) { - for callback in callbacks { - if let Some(cb) = callback.downcast_ref::>() { - if let Err(e) = cb.run(ctx, &value).await { - log::error!("Error in event callback: {:?}", e); + async fn handle_event(&self, ctx: Context, value: T) { + let callbacks = self.callbacks.clone(); + + tokio::spawn(async move { + let value = value; + if let Some(callbacks) = callbacks.get(&TypeId::of::()) { + for callback in callbacks { + if let Some(cb) = callback.downcast_ref::>() { + if let Err(e) = cb.run(&ctx, &value).await { + log::error!("Error in event callback: {:?}", e); + } } } } - } + }); } pub fn add_event(&mut self, cb: F) -> &mut Self @@ -76,7 +81,7 @@ impl RichEventHandler { self.callbacks.insert(type_id, Vec::new()); self.callbacks.get_mut(&type_id).unwrap() }; - callbacks.push(Box::new(EventCallback { + callbacks.push(Arc::new(EventCallback { inner: Arc::new(cb), })); @@ -122,44 +127,44 @@ impl Default for RichEventHandler { impl RawEventHandler for RichEventHandler { async fn raw_event(&self, ctx: Context, event: Event) { match event { - Event::ChannelCreate(e) => self.handle_event(&ctx, e).await, - Event::ChannelDelete(e) => self.handle_event(&ctx, e).await, - Event::ChannelPinsUpdate(e) => self.handle_event(&ctx, e).await, - Event::ChannelUpdate(e) => self.handle_event(&ctx, e).await, - Event::GuildBanAdd(e) => self.handle_event(&ctx, e).await, - Event::GuildBanRemove(e) => self.handle_event(&ctx, e).await, - Event::GuildCreate(e) => self.handle_event(&ctx, e).await, - Event::GuildDelete(e) => self.handle_event(&ctx, e).await, - Event::GuildEmojisUpdate(e) => self.handle_event(&ctx, e).await, - Event::GuildIntegrationsUpdate(e) => self.handle_event(&ctx, e).await, - Event::GuildMemberAdd(e) => self.handle_event(&ctx, e).await, - Event::GuildMemberRemove(e) => self.handle_event(&ctx, e).await, - Event::GuildMemberUpdate(e) => self.handle_event(&ctx, e).await, - Event::GuildMembersChunk(e) => self.handle_event(&ctx, e).await, - Event::GuildRoleCreate(e) => self.handle_event(&ctx, e).await, - Event::GuildRoleDelete(e) => self.handle_event(&ctx, e).await, - Event::GuildRoleUpdate(e) => self.handle_event(&ctx, e).await, - Event::GuildUnavailable(e) => self.handle_event(&ctx, e).await, - Event::GuildUpdate(e) => self.handle_event(&ctx, e).await, - Event::InviteCreate(e) => self.handle_event(&ctx, e).await, - Event::InviteDelete(e) => self.handle_event(&ctx, e).await, - Event::MessageCreate(e) => self.handle_event(&ctx, e).await, - Event::MessageDelete(e) => self.handle_event(&ctx, e).await, - Event::MessageDeleteBulk(e) => self.handle_event(&ctx, e).await, - Event::MessageUpdate(e) => self.handle_event(&ctx, e).await, - Event::PresenceUpdate(e) => self.handle_event(&ctx, e).await, - Event::PresencesReplace(e) => self.handle_event(&ctx, e).await, - Event::ReactionAdd(e) => self.handle_event(&ctx, e).await, - Event::ReactionRemove(e) => self.handle_event(&ctx, e).await, - Event::ReactionRemoveAll(e) => self.handle_event(&ctx, e).await, - Event::Ready(e) => self.handle_event(&ctx, e).await, - Event::Resumed(e) => self.handle_event(&ctx, e).await, - Event::TypingStart(e) => self.handle_event(&ctx, e).await, - Event::UserUpdate(e) => self.handle_event(&ctx, e).await, - Event::VoiceStateUpdate(e) => self.handle_event(&ctx, e).await, - Event::VoiceServerUpdate(e) => self.handle_event(&ctx, e).await, - Event::WebhookUpdate(e) => self.handle_event(&ctx, e).await, - Event::Unknown(e) => self.handle_event(&ctx, e).await, + Event::ChannelCreate(e) => self.handle_event(ctx, e).await, + Event::ChannelDelete(e) => self.handle_event(ctx, e).await, + Event::ChannelPinsUpdate(e) => self.handle_event(ctx, e).await, + Event::ChannelUpdate(e) => self.handle_event(ctx, e).await, + Event::GuildBanAdd(e) => self.handle_event(ctx, e).await, + Event::GuildBanRemove(e) => self.handle_event(ctx, e).await, + Event::GuildCreate(e) => self.handle_event(ctx, e).await, + Event::GuildDelete(e) => self.handle_event(ctx, e).await, + Event::GuildEmojisUpdate(e) => self.handle_event(ctx, e).await, + Event::GuildIntegrationsUpdate(e) => self.handle_event(ctx, e).await, + Event::GuildMemberAdd(e) => self.handle_event(ctx, e).await, + Event::GuildMemberRemove(e) => self.handle_event(ctx, e).await, + Event::GuildMemberUpdate(e) => self.handle_event(ctx, e).await, + Event::GuildMembersChunk(e) => self.handle_event(ctx, e).await, + Event::GuildRoleCreate(e) => self.handle_event(ctx, e).await, + Event::GuildRoleDelete(e) => self.handle_event(ctx, e).await, + Event::GuildRoleUpdate(e) => self.handle_event(ctx, e).await, + Event::GuildUnavailable(e) => self.handle_event(ctx, e).await, + Event::GuildUpdate(e) => self.handle_event(ctx, e).await, + Event::InviteCreate(e) => self.handle_event(ctx, e).await, + Event::InviteDelete(e) => self.handle_event(ctx, e).await, + Event::MessageCreate(e) => self.handle_event(ctx, e).await, + Event::MessageDelete(e) => self.handle_event(ctx, e).await, + Event::MessageDeleteBulk(e) => self.handle_event(ctx, e).await, + Event::MessageUpdate(e) => self.handle_event(ctx, e).await, + Event::PresenceUpdate(e) => self.handle_event(ctx, e).await, + Event::PresencesReplace(e) => self.handle_event(ctx, e).await, + Event::ReactionAdd(e) => self.handle_event(ctx, e).await, + Event::ReactionRemove(e) => self.handle_event(ctx, e).await, + Event::ReactionRemoveAll(e) => self.handle_event(ctx, e).await, + Event::Ready(e) => self.handle_event(ctx, e).await, + Event::Resumed(e) => self.handle_event(ctx, e).await, + Event::TypingStart(e) => self.handle_event(ctx, e).await, + Event::UserUpdate(e) => self.handle_event(ctx, e).await, + Event::VoiceStateUpdate(e) => self.handle_event(ctx, e).await, + Event::VoiceServerUpdate(e) => self.handle_event(ctx, e).await, + Event::WebhookUpdate(e) => self.handle_event(ctx, e).await, + Event::Unknown(e) => self.handle_event(ctx, e).await, _ => {} } }