From 6db631a432ee916380b62770357adb46edd7c281 Mon Sep 17 00:00:00 2001 From: Divy Srivastava Date: Tue, 9 Jan 2024 19:56:54 +0530 Subject: fix(ext/websocket): pass on uncaught errors in idleTimeout (#21846) Fixes https://github.com/denoland/deno/issues/21840 The problem was hard to reproduce as its a race condition. I've added a test that reproduces the problem 1/10 tries. We should move the idleTimeout handling to Rust (maybe even built into fastwebsocket). --- test_util/src/servers/mod.rs | 48 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) (limited to 'test_util/src') diff --git a/test_util/src/servers/mod.rs b/test_util/src/servers/mod.rs index 304d450b4..d4c40f4fc 100644 --- a/test_util/src/servers/mod.rs +++ b/test_util/src/servers/mod.rs @@ -455,6 +455,54 @@ async fn main_server( ); Ok(response) } + (&Method::GET, "/ghost_ws_client") => { + use tokio::io::AsyncReadExt; + + let mut tcp_stream = TcpStream::connect("localhost:4248").await.unwrap(); + #[cfg(unix)] + // SAFETY: set socket keep alive. + unsafe { + use std::os::fd::AsRawFd; + + let fd = tcp_stream.as_raw_fd(); + let mut val: libc::c_int = 1; + let r = libc::setsockopt( + fd, + libc::SOL_SOCKET, + libc::SO_KEEPALIVE, + &mut val as *mut _ as *mut libc::c_void, + std::mem::size_of_val(&val) as libc::socklen_t, + ); + assert_eq!(r, 0); + } + + // Typical websocket handshake request. + let headers = [ + "GET / HTTP/1.1", + "Host: localhost", + "Upgrade: websocket", + "Connection: Upgrade", + "Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==", + "Sec-WebSocket-Version: 13", + "\r\n", + ] + .join("\r\n"); + tcp_stream.write_all(headers.as_bytes()).await.unwrap(); + + let mut buf = [0u8; 200]; + let n = tcp_stream.read(&mut buf).await.unwrap(); + assert!(n > 0); + + // Ghost the server: + // - Close the read half of the connection. + // - forget the TcpStream. + let tcp_stream = tcp_stream.into_std().unwrap(); + let _ = tcp_stream.shutdown(std::net::Shutdown::Read); + std::mem::forget(tcp_stream); + + let res = Response::new(empty_body()); + Ok(res) + } (_, "/multipart_form_data.txt") => { let b = "Preamble\r\n\ --boundary\t \r\n\ -- cgit v1.2.3