From ff05532723004e1e8e3c9f44314a3d7a90ac050c Mon Sep 17 00:00:00 2001 From: Michael Bolin Date: Mon, 20 Apr 2026 19:23:30 -0700 Subject: [PATCH] refactor: narrow async lock scopes (#18418) ## Why This is part of the follow-up work from #18178 to make Codex ready for Clippy's [`await_holding_lock`](https://rust-lang.github.io/rust-clippy/master/index.html#await_holding_lock) / [`await_holding_invalid_type`](https://rust-lang.github.io/rust-clippy/master/index.html#await_holding_invalid_type) lints. This bottom PR keeps the scope intentionally small: `NetworkProxyState::record_blocked()` only needs the state write lock while it mutates the blocked-request ring buffer and counters. The debug log payload and `BlockedRequestObserver` callback can be produced after that lock is released. ## What changed - Copies the blocked-request snapshot values needed for logging while updating the state. - Releases the `RwLockWriteGuard` before logging or notifying the observer. ## Verification - `cargo test -p codex-network-proxy` --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/openai/codex/pull/18418). * #18698 * #18423 * __->__ #18418 --- codex-rs/network-proxy/src/runtime.rs | 31 ++++++++++++--------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/codex-rs/network-proxy/src/runtime.rs b/codex-rs/network-proxy/src/runtime.rs index da090a69d..daafeec73 100644 --- a/codex-rs/network-proxy/src/runtime.rs +++ b/codex-rs/network-proxy/src/runtime.rs @@ -420,32 +420,29 @@ impl NetworkProxyState { let blocked_for_observer = entry.clone(); let blocked_request_observer = self.blocked_request_observer.read().await.clone(); let violation_line = blocked_request_violation_log_line(&entry); - let mut guard = self.state.write().await; let host = entry.host.clone(); let reason = entry.reason.clone(); let decision = entry.decision.clone(); let source = entry.source.clone(); let protocol = entry.protocol.clone(); let port = entry.port; - guard.blocked.push_back(entry); - guard.blocked_total = guard.blocked_total.saturating_add(1); - let total = guard.blocked_total; - while guard.blocked.len() > MAX_BLOCKED_EVENTS { - guard.blocked.pop_front(); - } + let (total, buffered) = { + let mut guard = self.state.write().await; + guard.blocked.push_back(entry); + guard.blocked_total = guard.blocked_total.saturating_add(1); + let total = guard.blocked_total; + while guard.blocked.len() > MAX_BLOCKED_EVENTS { + guard.blocked.pop_front(); + } + (total, guard.blocked.len()) + }; debug!( - "recorded blocked request telemetry (total={}, host={}, reason={}, decision={:?}, source={:?}, protocol={}, port={:?}, buffered={})", - total, - host, - reason, - decision, - source, - protocol, - port, - guard.blocked.len() + "recorded blocked request telemetry (\ + total={total}, host={host}, reason={reason}, \ + decision={decision:?}, source={source:?}, \ + protocol={protocol}, port={port:?}, buffered={buffered})" ); debug!("{violation_line}"); - drop(guard); if let Some(observer) = blocked_request_observer { observer.on_blocked_request(blocked_for_observer).await;