From f0e3c430a069bae9c68d169955027aef11c2eaef Mon Sep 17 00:00:00 2001 From: Dotta Date: Fri, 11 Sep 2026 15:31:33 -0500 Subject: [PATCH] Wait for request bytes in fake Anthropic service sockets --- .../src/claude_managed_provider.rs | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/packages/paperclip-runner/runner/crates/runner-core/src/claude_managed_provider.rs b/packages/paperclip-runner/runner/crates/runner-core/src/claude_managed_provider.rs index 8d68b2212b..da44421ad4 100644 --- a/packages/paperclip-runner/runner/crates/runner-core/src/claude_managed_provider.rs +++ b/packages/paperclip-runner/runner/crates/runner-core/src/claude_managed_provider.rs @@ -2670,6 +2670,9 @@ mod tests { } fn read_http_request(socket: &mut TcpStream) -> Result { + // Darwin inherits the listener's nonblocking flag on accept. Wait for + // request bytes within the timeout instead of dropping an early accept. + socket.set_nonblocking(false)?; socket.set_read_timeout(Some(Duration::from_secs(2)))?; let mut bytes = Vec::new(); let mut buffer = [0_u8; 4096]; @@ -2722,6 +2725,34 @@ mod tests { }) } + #[test] + fn fake_service_waits_for_request_bytes_on_an_accepted_nonblocking_socket() { + let listener = TcpListener::bind("127.0.0.1:0").unwrap(); + let mut client = TcpStream::connect(listener.local_addr().unwrap()).unwrap(); + let (mut accepted, _) = listener.accept().unwrap(); + // Reproduce Darwin's inherited listener flag on every test platform. + accepted.set_nonblocking(true).unwrap(); + let (result_tx, result_rx) = mpsc::channel(); + let reader = thread::spawn(move || { + result_tx.send(read_http_request(&mut accepted)).unwrap(); + }); + assert!(matches!( + result_rx.recv_timeout(Duration::from_millis(25)), + Err(mpsc::RecvTimeoutError::Timeout) + )); + client + .write_all(b"POST /delayed HTTP/1.1\r\nContent-Length: 2\r\n\r\n{}") + .unwrap(); + let request = result_rx + .recv_timeout(Duration::from_secs(3)) + .unwrap() + .unwrap(); + reader.join().unwrap(); + assert_eq!(request.method, "POST"); + assert_eq!(request.path, "/delayed"); + assert_eq!(request.body, "{}"); + } + fn send_json_response(socket: &mut TcpStream, status: &str, value: &Value) { let body = serde_json::to_string(value).unwrap(); let _ = write!(socket, "HTTP/1.1 {status}\r\nContent-Type: application/json\r\nContent-Length: {}\r\nConnection: close\r\n\r\n{body}", body.len());