[6/6] Fail exec client operations after disconnect (#18027)

## Summary
- Reject new exec-server client operations once the transport has
disconnected.
- Convert pending RPC calls into closed errors instead of synthetic
server errors.
- Cover pending read and later write behavior after remote executor
disconnect.

## Verification
- `just fmt`
- `cargo check -p codex-exec-server`

## Stack
```text
@  #18027 [6/6] Fail exec client operations after disconnect
│
o  #18212 [5/6] Wire executor-backed MCP stdio
│
o  #18087 [4/6] Abstract MCP stdio server launching
│
o  #18020 [3/6] Add pushed exec process events
│
o  #18086 [2/6] Support piped stdin in exec process API
│
o  #18085 [1/6] Add MCP server environment config
│
o  main
```

---------

Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
Ahmed Ibrahim
2026-04-20 16:24:06 -07:00
committed by GitHub
Unverified
parent 0f1c9b8963
commit 9ef1cab6f7
4 changed files with 225 additions and 102 deletions
+38 -1
View File
@@ -195,9 +195,46 @@ fn map_remote_error(error: ExecServerError) -> io::Error {
io::Error::new(io::ErrorKind::InvalidInput, message)
}
ExecServerError::Server { message, .. } => io::Error::other(message),
ExecServerError::Closed => {
ExecServerError::Closed | ExecServerError::Disconnected(_) => {
io::Error::new(io::ErrorKind::BrokenPipe, "exec-server transport closed")
}
_ => io::Error::other(error.to_string()),
}
}
#[cfg(test)]
mod tests {
use pretty_assertions::assert_eq;
use super::*;
#[test]
fn transport_errors_map_to_broken_pipe() {
let errors = [
ExecServerError::Closed,
ExecServerError::Disconnected("exec-server transport disconnected".to_string()),
];
let mapped_errors = errors
.into_iter()
.map(|error| {
let error = map_remote_error(error);
(error.kind(), error.to_string())
})
.collect::<Vec<_>>();
assert_eq!(
mapped_errors,
vec![
(
io::ErrorKind::BrokenPipe,
"exec-server transport closed".to_string()
),
(
io::ErrorKind::BrokenPipe,
"exec-server transport closed".to_string()
),
]
);
}
}