Skip to content

Commit

Permalink
Merge pull request #54 from Allen-Webb/crash
Browse files Browse the repository at this point in the history
Do not panic when pty closes
  • Loading branch information
cardoe authored Jan 31, 2024
2 parents de6760a + b5b515e commit 85ae008
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 2 deletions.
6 changes: 4 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -325,10 +325,11 @@ impl Log for StdErrLog {
Level::Trace => Color::Blue,
};
{
// A failure here indicates the stream closed. Do not panic.
writer
.get_mut()
.set_color(ColorSpec::new().set_fg(Some(color)))
.expect("failed to set color");
.ok();
}

if self.show_module_names {
Expand Down Expand Up @@ -359,7 +360,8 @@ impl Log for StdErrLog {
}
let _ = writeln!(writer, "{}", record.args());
{
writer.get_mut().reset().expect("failed to reset the color");
// A failure here indicates the stream closed. Do not panic.
writer.get_mut().reset().ok();
}
}

Expand Down
69 changes: 69 additions & 0 deletions tests/pty_closed.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#[cfg(unix)]
mod unix {
use std::fs::File;
use std::io::Error;
use std::os::unix::io::{AsRawFd, FromRawFd};

use log::info;

fn check_ret(ret: libc::c_int, err_msg: &str) {
if ret < 0 {
panic!("{}: {}", err_msg, Error::last_os_error());
}
}

fn wrap_fd(fd: libc::c_int, err_msg: &str) -> File {
check_ret(fd, err_msg);
// Use File as a owned fd.
unsafe { File::from_raw_fd(fd) }
}

#[test]
fn log_after_pty_close() {
let pt = wrap_fd(unsafe { libc::getpt() }, "getpt");
check_ret(unsafe { libc::grantpt(pt.as_raw_fd()) }, "grantpt");
check_ret(unsafe { libc::unlockpt(pt.as_raw_fd()) }, "unlockpt");

let name = unsafe { libc::ptsname(pt.as_raw_fd()) };
if name.is_null() {
panic!("ptsname: {}", Error::last_os_error());
}

let client = wrap_fd(unsafe { libc::open(name, libc::O_RDWR) }, "open client pty");

// Back up stderr
let dup_stderr = wrap_fd(unsafe { libc::dup(2) }, "dup stderr");
let dup_stderr_panic = wrap_fd(unsafe { libc::dup(2) }, "dup stderr");

// Set up the panic handler to restore stderr.
let default_panic = std::panic::take_hook();
std::panic::set_hook(Box::new(move |info| {
check_ret(
unsafe { libc::dup2(dup_stderr_panic.as_raw_fd(), 2) },
"dup2 restore stderr",
);
default_panic(info);
}));

// Replace stderr with pty
check_ret(
unsafe { libc::dup2(client.as_raw_fd(), 2) },
"dup2 restore stderr",
);

stderrlog::new().verbosity(50).init().unwrap();
info!("This should work.");

println!("Closing PTY");
drop(pt);

println!("Sending log after PTY closed");
info!("This should trigger an EIO.");

// Restore stderr
check_ret(
unsafe { libc::dup2(dup_stderr.as_raw_fd(), 2) },
"dup2 restore stderr",
);
}
}

0 comments on commit 85ae008

Please sign in to comment.