Bubble up the errors in set_nonblocking and set_cloexec

This commit is contained in:
Tobias Bucher 2016-06-24 11:31:58 +02:00
parent a32244b3d9
commit 9347ffcf5c
4 changed files with 30 additions and 30 deletions

View File

@ -62,32 +62,31 @@ impl FileDesc {
}
#[cfg(not(any(target_env = "newlib", target_os = "solaris", target_os = "emscripten")))]
pub fn set_cloexec(&self) {
pub fn set_cloexec(&self) -> io::Result<()> {
unsafe {
let ret = libc::ioctl(self.fd, libc::FIOCLEX);
assert_eq!(ret, 0);
cvt(libc::ioctl(self.fd, libc::FIOCLEX))?;
Ok(())
}
}
#[cfg(any(target_env = "newlib", target_os = "solaris", target_os = "emscripten"))]
pub fn set_cloexec(&self) {
pub fn set_cloexec(&self) -> io::Result<()> {
unsafe {
let previous = libc::fcntl(self.fd, libc::F_GETFD);
let ret = libc::fcntl(self.fd, libc::F_SETFD, previous | libc::FD_CLOEXEC);
assert_eq!(ret, 0);
let previous = cvt(libc::fcntl(self.fd, libc::F_GETFD))?;
cvt(libc::fcntl(self.fd, libc::F_SETFD, previous | libc::FD_CLOEXEC))?;
Ok(())
}
}
pub fn set_nonblocking(&self, nonblocking: bool) {
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
unsafe {
let previous = libc::fcntl(self.fd, libc::F_GETFL);
assert!(previous != -1);
let previous = cvt(libc::fcntl(self.fd, libc::F_GETFL))?;
let new = if nonblocking {
previous | libc::O_NONBLOCK
} else {
previous & !libc::O_NONBLOCK
};
let ret = libc::fcntl(self.fd, libc::F_SETFL, new);
assert!(ret != -1);
cvt(libc::fcntl(self.fd, libc::F_SETFL, new))?;
Ok(())
}
}
@ -114,8 +113,8 @@ impl FileDesc {
let make_filedesc = |fd| {
let fd = FileDesc::new(fd);
fd.set_cloexec();
fd
fd.set_cloexec()?;
Ok(fd)
};
static TRY_CLOEXEC: AtomicBool =
AtomicBool::new(!cfg!(target_os = "android"));
@ -127,7 +126,7 @@ impl FileDesc {
// though it reported doing so on F_DUPFD_CLOEXEC.
Ok(fd) => {
return Ok(if cfg!(target_os = "linux") {
make_filedesc(fd)
make_filedesc(fd)?
} else {
FileDesc::new(fd)
})
@ -138,7 +137,7 @@ impl FileDesc {
Err(e) => return Err(e),
}
}
cvt(unsafe { libc::fcntl(fd, libc::F_DUPFD, 0) }).map(make_filedesc)
cvt(unsafe { libc::fcntl(fd, libc::F_DUPFD, 0) }).and_then(make_filedesc)
}
}

View File

@ -418,7 +418,7 @@ impl File {
// The CLOEXEC flag, however, is supported on versions of OSX/BSD/etc
// that we support, so we only do this on Linux currently.
if cfg!(target_os = "linux") {
fd.set_cloexec();
fd.set_cloexec()?;
}
Ok(File(fd))

View File

@ -77,7 +77,7 @@ impl Socket {
let fd = cvt(libc::socket(fam, ty, 0))?;
let fd = FileDesc::new(fd);
fd.set_cloexec();
fd.set_cloexec()?;
Ok(Socket(fd))
}
}
@ -99,9 +99,9 @@ impl Socket {
cvt(libc::socketpair(fam, ty, 0, fds.as_mut_ptr()))?;
let a = FileDesc::new(fds[0]);
a.set_cloexec();
let b = FileDesc::new(fds[1]);
b.set_cloexec();
a.set_cloexec()?;
b.set_cloexec()?;
Ok((Socket(a), Socket(b)))
}
}
@ -132,7 +132,7 @@ impl Socket {
libc::accept(self.0.raw(), storage, len)
})?;
let fd = FileDesc::new(fd);
fd.set_cloexec();
fd.set_cloexec()?;
Ok(Socket(fd))
}

View File

@ -44,17 +44,18 @@ pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
}
}
if unsafe { libc::pipe(fds.as_mut_ptr()) == 0 } {
Ok((AnonPipe::from_fd(fds[0]), AnonPipe::from_fd(fds[1])))
let fd0 = FileDesc::new(fds[0]);
let fd1 = FileDesc::new(fds[1]);
Ok((AnonPipe::from_fd(fd0)?, AnonPipe::from_fd(fd1)?))
} else {
Err(io::Error::last_os_error())
}
}
impl AnonPipe {
pub fn from_fd(fd: libc::c_int) -> AnonPipe {
let fd = FileDesc::new(fd);
fd.set_cloexec();
AnonPipe(fd)
pub fn from_fd(fd: FileDesc) -> io::Result<AnonPipe> {
fd.set_cloexec()?;
Ok(AnonPipe(fd))
}
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
@ -81,8 +82,8 @@ pub fn read2(p1: AnonPipe,
// in the `select` loop below, and we wouldn't want one to block the other!
let p1 = p1.into_fd();
let p2 = p2.into_fd();
p1.set_nonblocking(true);
p2.set_nonblocking(true);
p1.set_nonblocking(true)?;
p2.set_nonblocking(true)?;
let max = cmp::max(p1.raw(), p2.raw());
loop {
@ -114,11 +115,11 @@ pub fn read2(p1: AnonPipe,
}
};
if read(&p1, v1)? {
p2.set_nonblocking(false);
p2.set_nonblocking(false)?;
return p2.read_to_end(v2).map(|_| ());
}
if read(&p2, v2)? {
p1.set_nonblocking(false);
p1.set_nonblocking(false)?;
return p1.read_to_end(v1).map(|_| ());
}
}