From: Ian Jackson Date: Tue, 1 Jun 2021 12:58:22 +0000 (+0100) Subject: utils: Provide RawStdout and the associated SigPipeWriter X-Git-Tag: otter-0.7.0~154 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=commitdiff_plain;h=ac5622cba4405339f5fbad81432ff8e854d888b3;p=otter.git utils: Provide RawStdout and the associated SigPipeWriter Signed-off-by: Ian Jackson --- diff --git a/src/utils.rs b/src/utils.rs index 4b7c0704..4c239b34 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -694,6 +694,43 @@ where R: Read, W: Write { } } +pub struct SigPipeWriter(pub W); + +impl SigPipeWriter { + fn handle_err(e: io::Error) -> io::Error { + if e.kind() != ErrorKind::BrokenPipe { return e } + + match (||{ + use nix::sys::signal::*; + use Signal::SIGPIPE; + unsafe { + sigaction(SIGPIPE, &SigAction::new( + SigHandler::SigDfl, SaFlags::empty(), SigSet::empty())) + .context("sigaction")?; + }; + raise(SIGPIPE).context("raise")?; + Err::(anyhow!("continued after raise")) + })() { + Err(ae) => ae + .context("attempt to die with SIGPIPE failed") + .end_process(127), + Ok(v) => match v { }, + } + } +} + +impl Write for SigPipeWriter { + fn write(&mut self, buf: &[u8]) -> io::Result { + self.0.write(buf).map_err(Self::handle_err) + } + fn flush(&mut self) -> io::Result<()> { + self.0.flush() .map_err(Self::handle_err) + } +} + +pub type RawStdout = SigPipeWriter; +impl RawStdout { pub fn new() -> Self { SigPipeWriter(io::stdout()) } } + #[throws(fmt::Error)] pub fn fmt_hex(f: &mut Formatter, buf: &[u8]) { for v in buf { write!(f, "{:02x}", v)?; }