{"record":{"id":"8ee828c95f388090","repo":"RightNow-AI/openfang","slug":"failed-to-set-listener-to-non-blocking","errorCode":null,"errorMessage":"Failed to set listener to non-blocking","messagePattern":"Failed to set listener to non-blocking","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/openfang-desktop/src/server.rs","lineNumber":126,"sourceCode":"        server_thread: Some(server_thread),\n        shutdown_initiated,\n    })\n}\n\n/// Run the axum server inside a tokio runtime, shut down when the watch\n/// channel fires.\nasync fn run_embedded_server(\n    kernel: Arc<OpenFangKernel>,\n    std_listener: TcpListener,\n    listen_addr: SocketAddr,\n    mut shutdown_rx: watch::Receiver<bool>,\n) {\n    let (app, state) = build_router(kernel, listen_addr).await;\n\n    // Convert std TcpListener → tokio TcpListener\n    std_listener\n        .set_nonblocking(true)\n        .expect(\"Failed to set listener to non-blocking\");\n    let listener = tokio::net::TcpListener::from_std(std_listener)\n        .expect(\"Failed to convert std TcpListener to tokio\");\n\n    info!(\"OpenFang embedded server listening on http://{listen_addr}\");\n\n    let server = axum::serve(\n        listener,\n        app.into_make_service_with_connect_info::<SocketAddr>(),\n    )\n    .with_graceful_shutdown(async move {\n        let _ = shutdown_rx.wait_for(|v| *v).await;\n        info!(\"Embedded server received shutdown signal\");\n    });\n\n    if let Err(e) = server.await {\n        error!(\"Embedded server error: {e}\");\n    }\n","sourceCodeStart":108,"sourceCodeEnd":144,"githubUrl":"https://github.com/RightNow-AI/openfang/blob/acf2587e46be174c10200489c9a2d23a39a98aeb/crates/openfang-desktop/src/server.rs#L108-L144","documentation":"This panic comes from `std_listener.set_nonblocking(true).expect(...)` in run_embedded_server (crates/openfang-desktop/src/server.rs:126). Before wrapping the bound std::net::TcpListener with tokio via TcpListener::from_std, the socket must be switched to non-blocking mode, because from_std panics/errors on a blocking socket. set_nonblocking returns io::Result and fails only if the underlying syscall (fcntl ioctl FIONBIO) fails on the socket fd.","triggerScenarios":"Calling set_nonblocking on an std TcpListener whose file descriptor is invalid, already closed, or on which the OS refuses the FIONBIO ioctl (fd exhaustion, EBADF from a raced shutdown).","commonSituations":"Extremely rare in practice; typically seen when the listener fd was closed by another thread before this call, under fd-limit exhaustion, or on exotic platforms/embedded targets where the ioctl is unsupported.","solutions":["Log the underlying io::Error instead of panicking: map the expect to a Result and return it from run_embedded_server so the caller can shut down cleanly.","Verify the listener is still open (no concurrent close) between bind and this call.","Check the process fd limit (ulimit -n) if errors correlate with heavy load.","If conversion keeps failing, construct the tokio listener differently or retry the whole listener setup with a fresh bind."],"exampleFix":"// before\nstd_listener\n    .set_nonblocking(true)\n    .expect(\"Failed to set listener to non-blocking\");\n// after\nstd_listener\n    .set_nonblocking(true)\n    .map_err(|e| ServerError::ListenerSetup(format!(\"set_nonblocking: {e}\")))?;","handlingStrategy":"validation","validationCode":"// Before conversion, confirm the socket fd is still valid\nlet fd = std_listener.as_raw_fd();\nif fd < 0 {\n    return Err(\"listener fd already closed\");\n}","typeGuard":null,"tryCatchPattern":"match std_listener.set_nonblocking(true) {\n    Ok(()) => { /* proceed to from_std */ }\n    Err(e) => log::error!(\"set_nonblocking failed: {e}\"), // abort server startup cleanly\n}","preventionTips":["Always call set_nonblocking(true) directly before TcpListener::from_std — never skip it.","Do not close or move the std listener from other threads between bind and conversion.","Keep bind → set_nonblocking → from_std in one function so ordering is obvious.","Monitor fd usage (open files) if the server binds many listeners."],"tags":["rust","tokio","networking","tcp","io"],"backgroundTag":"set-nonblocking-failed","analyzedSha":"acf2587e46be174c10200489c9a2d23a39a98aeb","analyzedAt":"2026-09-02T22:42:28.464Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}