Rollup merge of #22739 - tbu-:pr_error_net, r=alexcrichton

This affects the `set_non_blocking` function which cannot fail for Unix or
Windows, given correct parameters. Additionally, the short UDP write error case
has been removed as there is no such thing as \"short UDP writes\", instead, the
operating system will error out if the application tries to send a packet
larger than the MTU of the network path.
This commit is contained in:
Manish Goregaokar 2015-02-25 03:20:51 +05:30
commit 5af3d660de
8 changed files with 37 additions and 31 deletions

View file

@ -503,7 +503,7 @@ pub fn connect_timeout(fd: sock_t,
#[cfg(windows)] use libc::WSAEWOULDBLOCK as WOULDBLOCK;
// Make sure the call to connect() doesn't block
try!(set_nonblocking(fd, true));
set_nonblocking(fd, true);
let ret = match unsafe { libc::connect(fd, addrp, len) } {
// If the connection is in progress, then we need to wait for it to
@ -533,7 +533,7 @@ pub fn connect_timeout(fd: sock_t,
};
// be sure to turn blocking I/O back on
try!(set_nonblocking(fd, false));
set_nonblocking(fd, false);
return ret;
#[cfg(unix)]
@ -626,7 +626,7 @@ pub struct Guard<'a> {
#[unsafe_destructor]
impl<'a> Drop for Guard<'a> {
fn drop(&mut self) {
assert!(set_nonblocking(self.fd, false).is_ok());
set_nonblocking(self.fd, false);
}
}
@ -723,7 +723,7 @@ fn lock_nonblocking<'a>(&'a self) -> Guard<'a> {
fd: self.fd(),
guard: self.inner.lock.lock().unwrap(),
};
assert!(set_nonblocking(self.fd(), true).is_ok());
set_nonblocking(self.fd(), true);
ret
}
@ -862,7 +862,7 @@ fn lock_nonblocking<'a>(&'a self) -> Guard<'a> {
fd: self.fd(),
guard: self.inner.lock.lock().unwrap(),
};
assert!(set_nonblocking(self.fd(), true).is_ok());
set_nonblocking(self.fd(), true);
ret
}
@ -887,9 +887,7 @@ pub fn recv_from(&mut self, buf: &mut [u8]) -> IoResult<(uint, SocketAddr)> {
storagep,
&mut addrlen) as libc::c_int
}));
sockaddr_to_addr(&storage, addrlen as uint).and_then(|addr| {
Ok((n as uint, addr))
})
Ok((n as uint, sockaddr_to_addr(&storage, addrlen as uint).unwrap()))
}
pub fn send_to(&mut self, buf: &[u8], dst: SocketAddr) -> IoResult<()> {
@ -910,11 +908,8 @@ pub fn send_to(&mut self, buf: &[u8], dst: SocketAddr) -> IoResult<()> {
};
let n = try!(write(fd, self.write_deadline, buf, false, dolock, dowrite));
if n != buf.len() {
Err(short_write(n, "couldn't send entire packet at once"))
} else {
Ok(())
}
assert!(n == buf.len(), "UDP packet not completely written.");
Ok(())
}
pub fn join_multicast(&mut self, multi: IpAddr) -> IoResult<()> {

View file

@ -214,9 +214,9 @@ pub fn wouldblock() -> bool {
err == libc::EWOULDBLOCK as i32 || err == libc::EAGAIN as i32
}
pub fn set_nonblocking(fd: sock_t, nb: bool) -> IoResult<()> {
pub fn set_nonblocking(fd: sock_t, nb: bool) {
let set = nb as libc::c_int;
mkerr_libc(retry(|| unsafe { c::ioctl(fd, c::FIONBIO, &set) }))
mkerr_libc(retry(|| unsafe { c::ioctl(fd, c::FIONBIO, &set) })).unwrap();
}
// nothing needed on unix platforms

View file

@ -235,9 +235,9 @@ pub fn listen(self) -> IoResult<UnixAcceptor> {
_ => {
let (reader, writer) = try!(unsafe { sys::os::pipe() });
try!(set_nonblocking(reader.fd(), true));
try!(set_nonblocking(writer.fd(), true));
try!(set_nonblocking(self.fd(), true));
set_nonblocking(reader.fd(), true);
set_nonblocking(writer.fd(), true);
set_nonblocking(self.fd(), true);
Ok(UnixAcceptor {
inner: Arc::new(AcceptorInner {
listener: self,

View file

@ -345,8 +345,8 @@ fn register_sigchld() -> (libc::c_int, c::sigaction) {
unsafe {
let mut pipes = [0; 2];
assert_eq!(libc::pipe(pipes.as_mut_ptr()), 0);
set_nonblocking(pipes[0], true).ok().unwrap();
set_nonblocking(pipes[1], true).ok().unwrap();
set_nonblocking(pipes[0], true);
set_nonblocking(pipes[1], true);
WRITE_FD = pipes[1];
let mut old: c::sigaction = mem::zeroed();
@ -362,7 +362,7 @@ fn register_sigchld() -> (libc::c_int, c::sigaction) {
fn waitpid_helper(input: libc::c_int,
messages: Receiver<Req>,
(read_fd, old): (libc::c_int, c::sigaction)) {
set_nonblocking(input, true).ok().unwrap();
set_nonblocking(input, true);
let mut set: c::fd_set = unsafe { mem::zeroed() };
let mut tv: libc::timeval;
let mut active = Vec::<(libc::pid_t, Sender<ProcessExit>, u64)>::new();

View file

@ -67,9 +67,9 @@ pub fn listen(self, backlog: int) -> IoResult<TcpAcceptor> {
-1 => Err(last_net_error()),
_ => {
let (reader, writer) = try!(unsafe { sys::os::pipe() });
try!(set_nonblocking(reader.fd(), true));
try!(set_nonblocking(writer.fd(), true));
try!(set_nonblocking(self.fd(), true));
set_nonblocking(reader.fd(), true);
set_nonblocking(writer.fd(), true);
set_nonblocking(self.fd(), true);
Ok(TcpAcceptor {
inner: Arc::new(AcceptorInner {
listener: self,

View file

@ -192,12 +192,12 @@ pub fn wouldblock() -> bool {
err == libc::WSAEWOULDBLOCK as i32
}
pub fn set_nonblocking(fd: sock_t, nb: bool) -> IoResult<()> {
pub fn set_nonblocking(fd: sock_t, nb: bool) {
let mut set = nb as libc::c_ulong;
if unsafe { c::ioctlsocket(fd, c::FIONBIO, &mut set) != 0 } {
Err(last_error())
} else {
Ok(())
if unsafe { c::ioctlsocket(fd, c::FIONBIO, &mut set) } != 0 {
// The above function should not return an error unless we passed it
// invalid parameters. Panic on errors.
Err(last_error()).unwrap();
}
}

View file

@ -25,6 +25,8 @@
pub struct Socket(libc::SOCKET);
/// Checks whether the Windows socket interface has been started already, and
/// if not, starts it.
pub fn init() {
static START: Once = ONCE_INIT;
@ -38,10 +40,16 @@ pub fn init() {
});
}
/// Returns the last error from the Windows socket interface.
fn last_error() -> io::Error {
io::Error::from_os_error(unsafe { c::WSAGetLastError() })
}
/// Checks if the signed integer is the Windows constant `SOCKET_ERROR` (-1)
/// and if so, returns the last error from the Windows socket interface. . This
/// function must be called before another call to the socket API is made.
///
/// FIXME: generics needed?
pub fn cvt<T: SignedInt>(t: T) -> io::Result<T> {
let one: T = Int::one();
if t == -one {
@ -51,11 +59,14 @@ pub fn cvt<T: SignedInt>(t: T) -> io::Result<T> {
}
}
/// Provides the functionality of `cvt` for the return values of `getaddrinfo`
/// and similar, meaning that they return an error if the return value is 0.
pub fn cvt_gai(err: c_int) -> io::Result<()> {
if err == 0 { return Ok(()) }
cvt(err).map(|_| ())
}
/// Provides the functionality of `cvt` for a closure.
pub fn cvt_r<T: SignedInt, F>(mut f: F) -> io::Result<T> where F: FnMut() -> T {
cvt(f())
}
@ -112,7 +123,7 @@ pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
impl Drop for Socket {
fn drop(&mut self) {
unsafe { let _ = libc::closesocket(self.0); }
unsafe { cvt(libc::closesocket(self.0)).unwrap(); }
}
}

View file

@ -192,7 +192,7 @@ pub fn accept(&mut self) -> IoResult<TcpStream> {
c::WSAEventSelect(socket, events[1], 0)
};
if ret != 0 { return Err(last_net_error()) }
try!(set_nonblocking(socket, false));
set_nonblocking(socket, false);
return Ok(stream)
}
}