refactor(admin): Release handle lock before command execution

Change admin service handle to SyncRwLock and copy the handler

function pointer before awaiting execution to prevent deadlock.
This commit is contained in:
Jade Ellis committed 2026-10-28 21:45:18 +00:00
1 parent 35d606eeb7
commit 938b3d2825
3 files changed
+13 -15

No files matched your search

+4 -8
View File
@@ -39,17 +39,13 @@ conduwuit::mod_dtor! {}
pub use crate::admin::AdminCommand;
/// Install the admin command processor
pub async fn init(admin_service: &service::admin::Service) {
pub fn init(admin_service: &service::admin::Service) {
_ = admin_service.complete.write().insert(processor::complete);
_ = admin_service
.handle
.write()
.await
.insert(processor::dispatch);
_ = admin_service.handle.write().insert(processor::dispatch);
}
/// Uninstall the admin command handler
pub async fn fini(admin_service: &service::admin::Service) {
_ = admin_service.handle.write().await.take();
pub fn fini(admin_service: &service::admin::Service) {
_ = admin_service.handle.write().take();
_ = admin_service.complete.write().take();
}
+2 -2
View File
@@ -25,7 +25,7 @@ pub(crate) async fn run(services: Arc<Services>) -> Result<()> {
debug!("Start");
// Install the admin room callback here for now
admin::init(&services.admin).await;
admin::init(&services.admin);
// Setup shutdown/signal handling
let handle = ServerHandle::new();
@@ -60,7 +60,7 @@ pub(crate) async fn run(services: Arc<Services>) -> Result<()> {
_ = sigs.await;
// Remove the admin room callback
admin::fini(&services.admin).await;
admin::fini(&services.admin);
debug_info!("Finish");
res
+7 -5
View File
@@ -27,7 +27,6 @@ use ruma::{
},
},
};
use tokio::sync::RwLock;
use crate::{
Dep, account_data, config, globals,
@@ -38,7 +37,7 @@ use crate::{
pub struct Service {
services: Services,
channel: (Sender<CommandInput>, Receiver<CommandInput>),
pub handle: RwLock<Option<Processor>>,
pub handle: SyncRwLock<Option<Processor>>,
pub complete: SyncRwLock<Option<Completer>>,
#[cfg(feature = "console")]
pub console: Arc<console::Console>,
@@ -131,7 +130,7 @@ impl crate::Service for Service {
media: args.depend::<crate::media::Service>("media"),
},
channel: loole::bounded(COMMAND_QUEUE_LIMIT),
handle: RwLock::new(None),
handle: SyncRwLock::new(None),
complete: SyncRwLock::new(None),
#[cfg(feature = "console")]
console: console::Console::new(&args),
@@ -372,8 +371,11 @@ impl Service {
}
async fn process_command(&self, command: CommandInput) -> ProcessorResult {
let handle_guard = self.handle.read().await;
let handle = handle_guard.as_ref().expect("Admin module is not loaded");
let handle = *self
.handle
.read()
.as_ref()
.expect("Admin module is not loaded");
let services = self
.services