pub(crate) fn write_child_stdin(
stdin: std::process::ChildStdin,
data: &str,
) -> std::io::Result<()> {
#[cfg(unix)]
let written = {
let mut blocked: libc::sigset_t = unsafe { std::mem::zeroed() };
let mut previous: libc::sigset_t = unsafe { std::mem::zeroed() };
unsafe {
libc::sigaddset(&raw mut blocked, libc::SIGPIPE);
libc::pthread_sigmask(libc::SIG_BLOCK, &raw const blocked, &raw mut previous);
}
let written = write_stdin_and_close(stdin, data);
unsafe {
let mut pending: libc::sigset_t = std::mem::zeroed();
libc::sigpending(&raw mut pending);
if libc::sigismember(&raw const pending, libc::SIGPIPE) == 1 {
let mut delivered: libc::c_int = 0;
libc::sigwait(&raw const blocked, &raw mut delivered);
}
libc::pthread_sigmask(libc::SIG_SETMASK, &raw const previous, std::ptr::null_mut());
}
written
};
#[cfg(not(unix))]
let written = write_stdin_and_close(stdin, data);
match written {
Ok(()) => Ok(()),
Err(error) if error.kind() == std::io::ErrorKind::BrokenPipe => Ok(()),
Err(error) => Err(error),
}
}
fn write_stdin_and_close(mut stdin: std::process::ChildStdin, data: &str) -> std::io::Result<()> {
use std::io::Write;
let written = stdin.write_all(data.as_bytes());
drop(stdin);
written
}
#[allow(dead_code)]
pub(crate) fn block_on<F: Future>(future: F) -> F::Output {
static PROVIDER_RUNTIME: std::sync::LazyLock<tokio::runtime::Runtime> =
std::sync::LazyLock::new(|| {
tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build()
.expect("Failed to create provider runtime")
});
match tokio::runtime::Handle::try_current() {
Ok(handle) => tokio::task::block_in_place(|| handle.block_on(future)),
Err(_) => PROVIDER_RUNTIME.block_on(future),
}
}