use std::os::unix::io::{FromRawFd, OwnedFd};
use anyhow::{Result, bail};
#[allow(unsafe_code)]
pub fn create_socketpair() -> Result<(OwnedFd, OwnedFd)> {
let mut fds: [libc::c_int; 2] = [-1, -1];
let rc = unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) };
if rc != 0 {
bail!("socketpair failed: {}", std::io::Error::last_os_error());
}
for &fd in &fds {
unsafe { libc::fcntl(fd, libc::F_SETFD, libc::FD_CLOEXEC) };
}
let master = unsafe { OwnedFd::from_raw_fd(fds[0]) };
let child = unsafe { OwnedFd::from_raw_fd(fds[1]) };
Ok((master, child))
}
#[cfg(test)]
mod tests {
use super::*;
use std::os::unix::io::AsRawFd;
#[test]
fn creates_connected_pair() {
let (master, child) = create_socketpair().unwrap();
assert!(master.as_raw_fd() >= 0);
assert!(child.as_raw_fd() >= 0);
assert_ne!(master.as_raw_fd(), child.as_raw_fd());
}
}