From e87579c053f04080476af90c5c3475df2350234d Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 15 Sep 2026 07:07:58 +0000 Subject: [PATCH] fix(stdlib): handle port binding error in std.web server gracefully - Replaced `unwrap()` calls on `tiny_http::Server::http` with matching the `Result`. - When binding fails (e.g. port already in use), it now returns a `RuntimeError` instead of crashing the VM with a panic. - `SERVER_RUNNING` is correctly set back to `false` on failure. - Updated `stdlib_tests.rs` to expect errors instead of panics for these conditions. Co-authored-by: Tcode-Motion <188012755+Tcode-Motion@users.noreply.github.com> --- stdlib/src/web.rs | 32 ++++++++++++++++++++--- stdlib/tests/stdlib_tests.rs | 50 +++++++++++------------------------- 2 files changed, 43 insertions(+), 39 deletions(-) diff --git a/stdlib/src/web.rs b/stdlib/src/web.rs index 500b9235..7af6437d 100644 --- a/stdlib/src/web.rs +++ b/stdlib/src/web.rs @@ -394,8 +394,20 @@ impl StdlibRegistry { return Ok(RuntimeValue::Str("Server already running".to_string())); } SERVER_RUNNING.store(true, Ordering::SeqCst); - let server = - Mutex::new(tiny_http::Server::http(format!("0.0.0.0:{}", port)).unwrap()); + let server_result = tiny_http::Server::http(format!("0.0.0.0:{}", port)); + let server = match server_result { + Ok(s) => Mutex::new(s), + Err(e) => { + SERVER_RUNNING.store(false, Ordering::SeqCst); + return Err(RuntimeError::new( + techscript_runtime::error::RuntimeErrorKind::InvalidOperation( + format!("Failed to bind server to port {}: {}", port, e), + ), + None, + None, + )); + } + }; thread::spawn(move || { while SERVER_RUNNING.load(Ordering::SeqCst) { let page = PAGE_CONTENT.lock().unwrap().clone(); @@ -462,8 +474,20 @@ impl StdlibRegistry { return Ok(RuntimeValue::Str("Server already running".to_string())); } SERVER_RUNNING.store(true, Ordering::SeqCst); - let server = - Mutex::new(tiny_http::Server::http(format!("0.0.0.0:{}", port)).unwrap()); + let server_result = tiny_http::Server::http(format!("0.0.0.0:{}", port)); + let server = match server_result { + Ok(s) => Mutex::new(s), + Err(e) => { + SERVER_RUNNING.store(false, Ordering::SeqCst); + return Err(RuntimeError::new( + techscript_runtime::error::RuntimeErrorKind::InvalidOperation( + format!("Failed to bind server to port {}: {}", port, e), + ), + None, + None, + )); + } + }; thread::spawn(move || { while SERVER_RUNNING.load(Ordering::SeqCst) { let page = PAGE_CONTENT.lock().unwrap().clone(); diff --git a/stdlib/tests/stdlib_tests.rs b/stdlib/tests/stdlib_tests.rs index 8fe9cdf7..be24384a 100644 --- a/stdlib/tests/stdlib_tests.rs +++ b/stdlib/tests/stdlib_tests.rs @@ -410,7 +410,7 @@ fn test_regex_operations() { #[test] fn test_web_module() { use std::net::TcpListener; - use std::panic; + let registry = StdlibRegistry::new(); let web = registry.get_module("std.web").unwrap(); @@ -433,50 +433,30 @@ fn test_web_module() { let listener = TcpListener::bind("0.0.0.0:0").unwrap(); let port = listener.local_addr().unwrap().port(); - // Test panic on `start` when port is in use - let start_result = panic::catch_unwind(panic::AssertUnwindSafe(|| { - let mut caps = HashSet::new(); - caps.insert(Capability::Network); - let mut ctx2 = RuntimeContext::new(RuntimeConfig { - strict_mode: false, - max_recursion_depth: 1000, - enable_assertions: true, - capabilities: caps, - }); - let _ = start.call( - &mut ctx2, - vec![ - RuntimeValue::Int(port as i64), - RuntimeValue::Str("