{"record":{"id":"d99abc73e60145ea","repo":"valeriansaliou/sonic","slug":"brokenpipe-d99abc","errorCode":null,"errorMessage":"BrokenPipe","messagePattern":"BrokenPipe","errorType":"exception","errorClass":"std::io::Error","httpStatus":null,"severity":"warning","filePath":"client/src/util.rs","lineNumber":138,"sourceCode":"                pass: impl AsRef<str>,\n                multiplexer: &$crate::SonicMultiplexer,\n            ) -> std::io::Result<Self> {\n                SonicChannel::<self::Mode>::connect::<T>(addr, pass, multiplexer)\n                    .map(|inner| Self { inner })\n            }\n\n            pub fn server_info(&self) -> &crate::events::ServerInfo {\n                &self.inner.server_info\n            }\n\n            pub fn channel_info(&self) -> &crate::events::ChannelInfo {\n                &self.inner.channel_info\n            }\n\n            fn quit_blocking_(&mut self) -> std::io::Result<()> {\n                self.quit()?\n                    .recv_timeout($crate::RECV_TIMEOUT)\n                    .map_err(|error| std::io::Error::new(std::io::ErrorKind::BrokenPipe, error))?\n            }\n        }\n\n        impl Drop for $low_level_ty {\n            #[inline]\n            fn drop(&mut self) {\n                if !self.inner.is_closed() {\n                    $crate::logging::log_trace!(concat!(\"[Drop] Quitting \", stringify!($low_level_ty)));\n                    self.quit_blocking_().unwrap_or_else(|error| crate::logging::log_error!(\"{error:?}\"));\n                }\n            }\n        }\n\n        #[cfg(feature = \"sync\")]\n        type BlockingChannel = $blocking_ty;\n\n        #[doc = concat!(\"A blocking way to interact with a Sonic Channel in \", stringify!($mode), \" mode.\")]\n        #[doc = concat!(\"\\n\\nWhen in an asynchronous context (e.g. using `tokio`), use [`\", stringify!($async_ty), \"`] instead.\")]","sourceCodeStart":120,"sourceCodeEnd":156,"githubUrl":"https://github.com/valeriansaliou/sonic/blob/e6a72da6a532bc3f31d7d93ef1e0964a1a5d01b2/client/src/util.rs#L120-L156","documentation":"In the generated blocking wrapper quit_blocking_, the oneshot recv_timeout(RECV_TIMEOUT) on the quit response is remapped to ErrorKind::BrokenPipe on timeout. A timeout here means the response never arrived because the channel's worker/dispatcher is gone. It indicates the channel died before the quit acknowledgement could be delivered.","triggerScenarios":"Calling the blocking quit variant when the connection task already exited (send succeeded but nobody responds), or the worker was killed between enqueue and reply; also RECV_TIMEOUT expiring due to extreme stalls.","commonSituations":"Double-quit or quit after a prior connection failure; Drop impls racing with manual quit; shutdown ordering issues in multithreaded apps.","solutions":["Treat BrokenPipe on quit as benign — the channel is already down; ignore or log it.","Quit only once and guard against Drop racing manual quit.","Reconnect if you still need a clean session teardown.","Verify the runtime is not being torn down while quit's reply is pending."],"exampleFix":"// before\nchannel.quit_blocking()?;\n// after\nif let Err(e) = channel.quit_blocking() {\n    if e.kind() != std::io::ErrorKind::BrokenPipe {\n        return Err(e);\n    } // already closed: fine\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"fn is_broken_pipe(e: &std::io::Error) -> bool {\n    e.kind() == std::io::ErrorKind::BrokenPipe\n}","tryCatchPattern":"if let Err(e) = channel.quit_blocking() {\n    if e.kind() != std::io::ErrorKind::BrokenPipe {\n        return Err(e);\n    }\n    // channel already dead: treat quit as done\n}","preventionTips":["Call quit only once; let Drop handle the rest","Ignore BrokenPipe on quit — it means the channel was already down","Keep the runtime alive until the quit acknowledgement arrives","Guard manual quit against Drop with a flag (Once/AtomicBool)"],"tags":["broken-pipe","blocking","timeout","rust"],"backgroundTag":"broken-pipe-channel-closed","analyzedSha":"e6a72da6a532bc3f31d7d93ef1e0964a1a5d01b2","analyzedAt":"2026-09-01T14:10:00.384Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T20:17:18.057Z"}