{"record":{"id":"31bbd3504cb8397e","repo":"shadowsocks/shadowsocks-rust","slug":"errno","errorCode":null,"errorMessage":"errno","messagePattern":"errno","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/daemonize/daemonize/error.rs","lineNumber":160,"sourceCode":"\nimpl Num for i64 {\n    fn is_err(&self) -> bool {\n        *self == -1\n    }\n}\n\nimpl Num for isize {\n    fn is_err(&self) -> bool {\n        *self == -1\n    }\n}\n\npub fn check_err<N: Num, F: FnOnce(Errno) -> ErrorKind>(ret: N, f: F) -> Result<N, ErrorKind> {\n    if ret.is_err() { Err(f(errno())) } else { Ok(ret) }\n}\n\npub fn errno() -> Errno {\n    std::io::Error::last_os_error().raw_os_error().expect(\"errno\")\n}\n","sourceCodeStart":142,"sourceCodeEnd":162,"githubUrl":"https://github.com/shadowsocks/shadowsocks-rust/blob/8eb0f0a65b1d976ab6bed5787327ef86529b0435/src/daemonize/daemonize/error.rs#L142-L162","documentation":"Panic in daemonize's errno(): std::io::Error::last_os_error().raw_os_error() returned None, meaning the last OS error had no raw errno. This should be nearly impossible (raw_os_error is None only for constructed io::Errors), and expect('errno') is an internal invariant check used by check_err and execute_child when reporting daemonization failures.","triggerScenarios":"check_err or execute_child detects a failed syscall return and calls errno(), but last_os_error() yields an io::Error whose raw_os_error() is None (non-OS io::Error active in the thread's error slot).","commonSituations":"A prior library call stored a custom (non-OS) io::Error in the thread-local last-error slot; interleaving with other FFI/io code that clobbers the last error between syscall failure and errno() read.","solutions":["Call errno() immediately after the failing syscall, before other io operations","Inspect preceding code that may have set a non-OS io::Error and handle it separately","Replace expect with a fallback error kind (ErrorKind::Other) instead of panicking in a daemonization path","Run the daemonization in the foreground with logging to capture the sequence of failing syscalls"],"exampleFix":"// before\npub fn errno() -> Errno {\n    std::io::Error::last_os_error().raw_os_error().expect(\"errno\")\n}\n// after\npub fn errno() -> Errno {\n    std::io::Error::last_os_error()\n        .raw_os_error()\n        .unwrap_or(libc::EIO)\n}","handlingStrategy":"fallback","validationCode":"// not applicable: errno() depends on thread-local OS state, not caller inputs","typeGuard":"fn last_raw_errno() -> Option<i32> {\n    std::io::Error::last_os_error().raw_os_error()\n}","tryCatchPattern":"// expect() panics cannot be caught in-process except via catch_unwind; prefer reading the errno yourself\nlet code = std::io::Error::last_os_error().raw_os_error().unwrap_or(libc::EIO);","preventionTips":["Read last_os_error immediately after a failing syscall, before other io/FFI calls","Avoid interleaving constructed io::Errors with syscall error reporting","Favor unwrap_or with a default errno in diagnostic helpers","Run daemonization flows in foreground first to surface syscall failures"],"tags":["rust","daemonize","unix","errno","panic"],"backgroundTag":"internal-invariant-violation","analyzedSha":"8eb0f0a65b1d976ab6bed5787327ef86529b0435","analyzedAt":"2026-09-09T12:20:43.168Z","contentChangedAt":"2026-09-09T12:20:43.168Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}