bxctl: escape error details, time out on admin.sock, AdminError::Io
M3a review findings 9, 10, 12, 13. A retrying error and every error detail can carry the inference server's body, so they are escaped like model text. Admin requests wait at most 30 s, so a stuck brokerd cannot hang bxctl or a chat turn. A failed write is AdminError::Io and stops handle_pending instead of being answered with another write. The usage line says what audit verify checks. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
//! A `brokerd` that accepts and never answers does not hang `bxctl` (M3a review finding 9).
|
||||
|
||||
use std::os::unix::net::UnixListener;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
use bxctl::admin::{ADMIN_TIMEOUT, request_with_timeout};
|
||||
use proto::{Empty, Message};
|
||||
|
||||
#[test]
|
||||
fn the_default_is_thirty_seconds() {
|
||||
assert_eq!(ADMIN_TIMEOUT, Duration::from_secs(30));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_silent_brokerd_is_an_error_after_the_timeout() {
|
||||
let dir = std::env::temp_dir().join(format!("bx-admin-timeout-{}", std::process::id()));
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let socket = dir.join("admin.sock");
|
||||
let listener = UnixListener::bind(&socket).unwrap();
|
||||
let held = std::thread::spawn(move || {
|
||||
let (stream, _) = listener.accept().unwrap();
|
||||
std::thread::sleep(Duration::from_millis(2_000));
|
||||
drop(stream);
|
||||
});
|
||||
|
||||
let started = Instant::now();
|
||||
let got = request_with_timeout(
|
||||
&socket,
|
||||
Message::Approvals(Empty {}),
|
||||
Duration::from_millis(200),
|
||||
);
|
||||
let took = started.elapsed();
|
||||
assert!(got.is_err(), "{got:?}");
|
||||
assert!(took < Duration::from_millis(1_500), "waited {took:?}");
|
||||
held.join().unwrap();
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
}
|
||||
Reference in New Issue
Block a user