From 5945251a60d4607ce5c66afd90f736d4ed75a4a3 Mon Sep 17 00:00:00 2001 From: Ren Amamiya Date: Wed, 29 Jul 2026 11:15:42 +0700 Subject: [PATCH] fix --- crates/chat/src/lib.rs | 14 +++++++++----- crates/chat_ui/src/lib.rs | 6 +++++- crates/workspace/src/lib.rs | 20 +++++++++++++++----- crates/workspace/src/sidebar/mod.rs | 6 +++--- 4 files changed, 32 insertions(+), 14 deletions(-) diff --git a/crates/chat/src/lib.rs b/crates/chat/src/lib.rs index 2754239..9ddd6b0 100644 --- a/crates/chat/src/lib.rs +++ b/crates/chat/src/lib.rs @@ -517,7 +517,7 @@ impl ChatRegistry { /// Emit an open room event. /// /// If the room is new, add it to the registry. - pub fn emit_room(&mut self, room: &Entity, cx: &mut Context) { + pub fn emit_room(&mut self, room: &Entity, window: &mut Window, cx: &mut Context) { // Get the room's ID. let id = room.read(cx).id; @@ -526,14 +526,18 @@ impl ChatRegistry { self.rooms.insert(0, room.to_owned()); } - // Emit the open room event. - cx.emit(ChatEvent::OpenRoom(id)); + // Emit the open room event deferred to avoid re-entrant reads + cx.defer_in(window, move |_this, _window, cx| { + cx.emit(ChatEvent::OpenRoom(id)); + }); } /// Close a room. - pub fn close_room(&mut self, id: u64, cx: &mut Context) { + pub fn close_room(&mut self, id: u64, window: &mut Window, cx: &mut Context) { if self.rooms.iter().any(|r| r.read(cx).id == id) { - cx.emit(ChatEvent::CloseRoom(id)); + cx.defer_in(window, move |_this, _window, cx| { + cx.emit(ChatEvent::CloseRoom(id)); + }); } } diff --git a/crates/chat_ui/src/lib.rs b/crates/chat_ui/src/lib.rs index 2e69f65..9b03442 100644 --- a/crates/chat_ui/src/lib.rs +++ b/crates/chat_ui/src/lib.rs @@ -262,7 +262,11 @@ impl ChatPanel { this.insert_message(message, false, cx); } RoomEvent::Reload => { - this.get_messages(window, cx); + // Defer to avoid re-entrant read on Room while + // emit_refresh holds a write lock (via refresh_rooms). + cx.defer_in(window, |this, window, cx| { + this.get_messages(window, cx); + }); } }; }, diff --git a/crates/workspace/src/lib.rs b/crates/workspace/src/lib.rs index 4276a86..d066ba4 100644 --- a/crates/workspace/src/lib.rs +++ b/crates/workspace/src/lib.rs @@ -221,13 +221,23 @@ impl Workspace { ); subscriptions.push( - // Observe the chat registry + // Observe the chat registry. + // Deferred via spawn to avoid potential re-entrancy if + // cx.observe fires synchronously during a chat.update. cx.observe(&chat, move |this, chat, cx| { let ids = this.panel_ids(cx); - - chat.update(cx, |this, cx| { - this.refresh_rooms(&ids, cx); - }); + let chat = chat.downgrade(); + cx.spawn(async move |this, cx| -> anyhow::Result<()> { + if let Some(chat) = chat.upgrade() { + this.update(cx, |_this, cx| { + chat.update(cx, |chat, cx| { + chat.refresh_rooms(&ids, cx); + }); + })?; + } + Ok(()) + }) + .detach(); }), ); diff --git a/crates/workspace/src/sidebar/mod.rs b/crates/workspace/src/sidebar/mod.rs index 18aaf45..9409d36 100644 --- a/crates/workspace/src/sidebar/mod.rs +++ b/crates/workspace/src/sidebar/mod.rs @@ -329,7 +329,7 @@ impl Sidebar { .organize(&public_key) .kind(RoomKind::Ongoing) }); - this.emit_room(&room, cx); + this.emit_room(&room, _window, cx); })?; // Reset the find panel @@ -373,9 +373,9 @@ impl Sidebar { let room = item.read(cx); let room_clone = item.clone(); let public_key = room.display_member(cx).public_key(); - let handler = cx.listener(move |_this, _ev, _window, cx| { + let handler = cx.listener(move |_this, _ev, window, cx| { ChatRegistry::global(cx).update(cx, |s, cx| { - s.emit_room(&room_clone, cx); + s.emit_room(&room_clone, window, cx); }); });