mirror of
https://github.com/outbackdingo/optimclaw.git
synced 2026-09-03 10:09:30 +00:00
* fix: release lock guards before awaiting channel send (#869) Clone `mpsc::Sender` out of `RwLock` before `.send().await` to prevent read guards from blocking write lock acquisition (shutdown/start) when the channel buffer is full. Fixed call sites: - src/channels/http.rs: process_message() - src/channels/web/server.rs: chat_send_handler(), chat_approval_handler() - src/channels/web/handlers/chat.rs: chat_send_handler(), chat_approval_handler() - src/channels/web/ws.rs: handle_client_message() (2 sites) - src/channels/wasm/wrapper.rs: process_emitted_messages() (2 impls, also scoped rate_limiter write lock per-iteration) Includes regression test: shutdown_completes_while_process_message_blocked Co-Authored-By: Claude Opus 4.6 <[email protected]> (cherry picked from commit 84802e1b89aaf07ba976db20bdbfdf749edbe332) * ci: fetch base branch before regression test check The regression-test-check workflow failed because origin/main wasn't available as a ref in the CI environment. actions/checkout@v4 fetches the PR merge ref history but doesn't make the base branch ref available for three-dot diff comparisons. Co-Authored-By: Claude Opus 4.6 <[email protected]> (cherry picked from commit 1d5a7bdc8ec071cdddf0e69d6053d49ca20a2b18) * chore(ci): rerun regression gate [skip-regression-check] (cherry picked from commit 784d444701471a1311b1f985e2f07be6f0527abf) --------- Co-authored-by: Umesh Kumar Singh <[email protected]> Co-authored-by: Claude Opus 4.6 <[email protected]>
This commit is contained in:
co-authored by
Umesh Kumar Singh
Claude Opus 4.6
parent
c937dfa315
commit
ef34943c14
@@ -37,11 +37,17 @@ pub async fn chat_send_handler(
|
||||
let msg_id = msg.id;
|
||||
let thread_id = msg.thread_id.clone();
|
||||
|
||||
let tx_guard = state.msg_tx.read().await;
|
||||
let tx = tx_guard.as_ref().ok_or((
|
||||
StatusCode::SERVICE_UNAVAILABLE,
|
||||
"Channel not started".to_string(),
|
||||
))?;
|
||||
// Clone sender to avoid holding RwLock read guard across send().await
|
||||
let tx = {
|
||||
let tx_guard = state.msg_tx.read().await;
|
||||
tx_guard
|
||||
.as_ref()
|
||||
.ok_or((
|
||||
StatusCode::SERVICE_UNAVAILABLE,
|
||||
"Channel not started".to_string(),
|
||||
))?
|
||||
.clone()
|
||||
};
|
||||
|
||||
tx.send(msg).await.map_err(|_| {
|
||||
(
|
||||
@@ -111,11 +117,17 @@ pub async fn chat_approval_handler(
|
||||
|
||||
let msg_id = msg.id;
|
||||
|
||||
let tx_guard = state.msg_tx.read().await;
|
||||
let tx = tx_guard.as_ref().ok_or((
|
||||
StatusCode::SERVICE_UNAVAILABLE,
|
||||
"Channel not started".to_string(),
|
||||
))?;
|
||||
// Clone sender to avoid holding RwLock read guard across send().await
|
||||
let tx = {
|
||||
let tx_guard = state.msg_tx.read().await;
|
||||
tx_guard
|
||||
.as_ref()
|
||||
.ok_or((
|
||||
StatusCode::SERVICE_UNAVAILABLE,
|
||||
"Channel not started".to_string(),
|
||||
))?
|
||||
.clone()
|
||||
};
|
||||
|
||||
tx.send(msg).await.map_err(|_| {
|
||||
(
|
||||
|
||||
+22
-10
@@ -973,11 +973,17 @@ async fn chat_send_handler(
|
||||
req.images.len()
|
||||
);
|
||||
|
||||
let tx_guard = state.msg_tx.read().await;
|
||||
let tx = tx_guard.as_ref().ok_or((
|
||||
StatusCode::SERVICE_UNAVAILABLE,
|
||||
"Channel not started".to_string(),
|
||||
))?;
|
||||
// Clone sender to avoid holding RwLock read guard across send().await
|
||||
let tx = {
|
||||
let tx_guard = state.msg_tx.read().await;
|
||||
tx_guard
|
||||
.as_ref()
|
||||
.ok_or((
|
||||
StatusCode::SERVICE_UNAVAILABLE,
|
||||
"Channel not started".to_string(),
|
||||
))?
|
||||
.clone()
|
||||
};
|
||||
|
||||
tracing::debug!("[chat_send_handler] Sending message through channel");
|
||||
tx.send(msg).await.map_err(|_| {
|
||||
@@ -1043,11 +1049,17 @@ async fn chat_approval_handler(
|
||||
|
||||
let msg_id = msg.id;
|
||||
|
||||
let tx_guard = state.msg_tx.read().await;
|
||||
let tx = tx_guard.as_ref().ok_or((
|
||||
StatusCode::SERVICE_UNAVAILABLE,
|
||||
"Channel not started".to_string(),
|
||||
))?;
|
||||
// Clone sender to avoid holding RwLock read guard across send().await
|
||||
let tx = {
|
||||
let tx_guard = state.msg_tx.read().await;
|
||||
tx_guard
|
||||
.as_ref()
|
||||
.ok_or((
|
||||
StatusCode::SERVICE_UNAVAILABLE,
|
||||
"Channel not started".to_string(),
|
||||
))?
|
||||
.clone()
|
||||
};
|
||||
|
||||
tx.send(msg).await.map_err(|_| {
|
||||
(
|
||||
|
||||
+12
-4
@@ -176,8 +176,12 @@ async fn handle_client_message(
|
||||
incoming = incoming.with_attachments(attachments);
|
||||
}
|
||||
|
||||
let tx_guard = state.msg_tx.read().await;
|
||||
if let Some(ref tx) = *tx_guard {
|
||||
// Clone sender to avoid holding RwLock read guard across send().await
|
||||
let tx = {
|
||||
let tx_guard = state.msg_tx.read().await;
|
||||
tx_guard.as_ref().cloned()
|
||||
};
|
||||
if let Some(tx) = tx {
|
||||
if tx.send(incoming).await.is_err() {
|
||||
let _ = direct_tx
|
||||
.send(WsServerMessage::Error {
|
||||
@@ -245,8 +249,12 @@ async fn handle_client_message(
|
||||
if let Some(ref tid) = thread_id {
|
||||
msg = msg.with_thread(tid);
|
||||
}
|
||||
let tx_guard = state.msg_tx.read().await;
|
||||
if let Some(ref tx) = *tx_guard {
|
||||
// Clone sender to avoid holding RwLock read guard across send().await
|
||||
let tx = {
|
||||
let tx_guard = state.msg_tx.read().await;
|
||||
tx_guard.as_ref().cloned()
|
||||
};
|
||||
if let Some(tx) = tx {
|
||||
let _ = tx.send(msg).await;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user