perf: fix NVIM_CONN deadlock and unoptimized lock across await point

This commit is contained in:
Riz Ashraf committed 2026-09-21 09:25:22 +01:00
1 parent 5715625220
commit 2c5953e4f5
1 file changed
+15 -6
+15 -6
View File
@@ -113,7 +113,7 @@ async fn get_socket_path() -> Result<String, String> {
} }
use std::sync::LazyLock; use std::sync::LazyLock;
use std::sync::Arc; use std::sync::Arc;
use tokio::sync::{Mutex, mpsc, oneshot}; use tokio::sync::{mpsc, oneshot};
use std::collections::HashMap; use std::collections::HashMap;
@@ -123,13 +123,15 @@ pub struct NvimRequest {
pub reply: oneshot::Sender<Result<rmpv::Value, String>>, pub reply: oneshot::Sender<Result<rmpv::Value, String>>,
} }
static NVIM_CONN: LazyLock<Arc<Mutex<Option<mpsc::Sender<NvimRequest>>>>> = LazyLock::new(|| Arc::new(Mutex::new(None))); static NVIM_CONN: LazyLock<Arc<std::sync::Mutex<Option<mpsc::Sender<NvimRequest>>>>> = LazyLock::new(|| Arc::new(std::sync::Mutex::new(None)));
async fn get_nvim_connection() -> Result<mpsc::Sender<NvimRequest>, String> { async fn get_nvim_connection() -> Result<mpsc::Sender<NvimRequest>, String> {
let mut conn_lock = NVIM_CONN.lock().await; {
if let Some(sender) = conn_lock.as_ref() { let conn_lock = NVIM_CONN.lock().unwrap();
if !sender.is_closed() { if let Some(sender) = conn_lock.as_ref() {
return Ok(sender.clone()); if !sender.is_closed() {
return Ok(sender.clone());
}
} }
} }
@@ -244,6 +246,13 @@ async fn get_nvim_connection() -> Result<mpsc::Sender<NvimRequest>, String> {
} }
}); });
let mut conn_lock = NVIM_CONN.lock().unwrap();
if let Some(existing_sender) = conn_lock.as_ref() {
if !existing_sender.is_closed() {
// Another task established the connection while we were waiting
return Ok(existing_sender.clone());
}
}
*conn_lock = Some(tx.clone()); *conn_lock = Some(tx.clone());
Ok(tx) Ok(tx)
} }