From 1326924dbbd1dec5af7df6ae1f4199161c1c9f35 Mon Sep 17 00:00:00 2001 From: WangRunji Date: Tue, 23 Apr 2019 00:36:48 +0800 Subject: [PATCH] fix errno = 0 and introduce macro 'try_libc' --- src/libos/src/errno.rs | 106 ++++++++++++++++++++++++++-- src/libos/src/fs/io_multiplexing.rs | 32 ++------- src/libos/src/fs/socket_file.rs | 35 +++------ src/libos/src/prelude.rs | 21 +++++- src/libos/src/syscall/mod.rs | 66 ++++++++--------- 5 files changed, 170 insertions(+), 90 deletions(-) diff --git a/src/libos/src/errno.rs b/src/libos/src/errno.rs index 3abfec08..78efa487 100644 --- a/src/libos/src/errno.rs +++ b/src/libos/src/errno.rs @@ -81,19 +81,111 @@ pub enum Errno { ENOLCK = 37, ENOSYS = 38, ENOTEMPTY = 39, + ELOOP = 40, + EWOULDBLOCK = 41, + ENOMSG = 42, + EIDRM = 43, + ECHRNG = 44, + EL2NSYNC = 45, + EL3HLT = 46, + EL3RST = 47, + ELNRNG = 48, + EUNATCH = 49, + ENOCSI = 50, + EL2HLT = 51, + EBADE = 52, + EBADR = 53, + EXFULL = 54, + ENOANO = 55, + EBADRQC = 56, + EBADSLT = 57, + EDEADLOCK = 58, + EBFONT = 59, + ENOSTR = 60, + ENODATA = 61, + ETIME = 62, + ENOSR = 63, + ENONET = 64, + ENOPKG = 65, + EREMOTE = 66, + ENOLINK = 67, + EADV = 68, + ESRMNT = 69, + ECOMM = 70, + EPROTO = 71, + EMULTIHOP = 72, + EDOTDOT = 73, + EBADMSG = 74, + EOVERFLOW = 75, + ENOTUNIQ = 76, + EBADFD = 77, + EREMCHG = 78, + ELIBACC = 79, + ELIBBAD = 80, + ELIBSCN = 81, + ELIBMAX = 82, + ELIBEXEC = 83, + EILSEQ = 84, + ERESTART = 85, + ESTRPIPE = 86, + EUSERS = 87, + ENOTSOCK = 88, + EDESTADDRREQ = 89, + EMSGSIZE = 90, + EPROTOTYPE = 91, + ENOPROTOOPT = 92, + EPROTONOSUPPORT = 93, + ESOCKTNOSUPPORT = 94, + EOPNOTSUPP = 95, + EPFNOSUPPORT = 96, + EAFNOSUPPORT = 97, + EADDRINUSE = 98, + EADDRNOTAVAIL = 99, + ENETDOWN = 100, + ENETUNREACH = 101, + ENETRESET = 102, + ECONNABORTED = 103, + ECONNRESET = 104, + ENOBUFS = 105, + EISCONN = 106, + ENOTCONN = 107, + ESHUTDOWN = 108, + ETOOMANYREFS = 109, + ETIMEDOUT = 110, + ECONNREFUSED = 111, + EHOSTDOWN = 112, + EHOSTUNREACH = 113, + EALREADY = 114, + EINPROGRESS = 115, + ESTALE = 116, + EUCLEAN = 117, + ENOTNAM = 118, + ENAVAIL = 119, + EISNAM = 120, + EREMOTEIO = 121, + EDQUOT = 122, + ENOMEDIUM = 123, + EMEDIUMTYPE = 124, + ECANCELED = 125, + ENOKEY = 126, + EKEYEXPIRED = 127, + EKEYREVOKED = 128, + EKEYREJECTED = 129, + EOWNERDEAD = 130, + ENOTRECOVERABLE = 131, + ERFKILL = 132, + EHWPOISON = 133, } impl Errno { pub fn as_retval(&self) -> i32 { -(*self as i32) } - pub fn from_retval(ret: i32) -> Self { - let ret = if ret <= 0 && ret >= -39 { - (-ret) as u8 - } else { - 0 - }; - unsafe { core::mem::transmute(ret) } + pub fn from_errno(mut errno: i32) -> Self { + if errno < 0 || errno > 133 { + errno = 0; + } + unsafe { core::mem::transmute(errno as u8) } } } diff --git a/src/libos/src/fs/io_multiplexing.rs b/src/libos/src/fs/io_multiplexing.rs index f3f52951..59e1c962 100644 --- a/src/libos/src/fs/io_multiplexing.rs +++ b/src/libos/src/fs/io_multiplexing.rs @@ -57,11 +57,7 @@ pub fn do_select( Some(tv) => (tv.tv_sec * 1000 + tv.tv_usec / 1000) as i32, }; - let ret = unsafe { libc::ocall::poll(polls.as_mut_ptr(), polls.len() as u64, timeout) }; - - if ret < 0 { - return errno!(Errno::from_retval(unsafe { libc::errno() }), ""); - } + let ret = try_libc!(libc::ocall::poll(polls.as_mut_ptr(), polls.len() as u64, timeout)); // convert fd back and write fdset readfds.clear(); @@ -96,14 +92,9 @@ pub fn do_poll(polls: &mut [libc::pollfd], timeout: c_int) -> Result Result { @@ -211,10 +202,7 @@ struct EpollFileInner { impl EpollFileInner { /// Create a new Linux epoll file descriptor pub fn new() -> Result { - let ret = unsafe { libc::ocall::epoll_create1(0) }; - if ret < 0 { - return errno!(Errno::from_retval(unsafe { libc::errno() }), ""); - } + let ret = try_libc!(libc::ocall::epoll_create1(0)); Ok(EpollFileInner { epoll_fd: ret }) } @@ -225,10 +213,7 @@ impl EpollFileInner { event: *const libc::epoll_event, ) -> Result<(), Error> { let ret = - unsafe { libc::ocall::epoll_ctl(self.epoll_fd, op, host_fd as c_int, event as *mut _) }; - if ret < 0 { - return errno!(Errno::from_retval(unsafe { libc::errno() }), ""); - } + try_libc!(libc::ocall::epoll_ctl(self.epoll_fd, op, host_fd as c_int, event as *mut _)); Ok(()) } @@ -239,17 +224,14 @@ impl EpollFileInner { events: &mut [libc::epoll_event], timeout: c_int, ) -> Result { - let ret = unsafe { + let ret = try_libc!( libc::ocall::epoll_wait( self.epoll_fd, events.as_mut_ptr(), events.len() as c_int, timeout, ) - }; - if ret < 0 { - return errno!(Errno::from_retval(unsafe { libc::errno() }), ""); - } + ); Ok(ret as usize) } } diff --git a/src/libos/src/fs/socket_file.rs b/src/libos/src/fs/socket_file.rs index a84f545a..baaa87f8 100644 --- a/src/libos/src/fs/socket_file.rs +++ b/src/libos/src/fs/socket_file.rs @@ -9,12 +9,8 @@ pub struct SocketFile { impl SocketFile { pub fn new(domain: c_int, socket_type: c_int, protocol: c_int) -> Result { - let ret = unsafe { libc::ocall::socket(domain, socket_type, protocol) }; - if ret < 0 { - errno!(Errno::from_retval(unsafe { libc::errno() }), "") - } else { - Ok(SocketFile { fd: ret }) - } + let ret = try_libc!(libc::ocall::socket(domain, socket_type, protocol)); + Ok(SocketFile { fd: ret }) } pub fn accept( @@ -23,12 +19,8 @@ impl SocketFile { addr_len: *mut libc::socklen_t, flags: c_int, ) -> Result { - let ret = unsafe { libc::ocall::accept4(self.fd, addr, addr_len, flags) }; - if ret < 0 { - errno!(Errno::from_retval(unsafe { libc::errno() }), "") - } else { - Ok(SocketFile { fd: ret }) - } + let ret = try_libc!(libc::ocall::accept4(self.fd, addr, addr_len, flags)); + Ok(SocketFile { fd: ret }) } pub fn fd(&self) -> c_int { @@ -40,28 +32,21 @@ impl Drop for SocketFile { fn drop(&mut self) { let ret = unsafe { libc::ocall::close(self.fd) }; if ret < 0 { - warn!("socket (host fd: {}) close failed", self.fd); + let errno = unsafe { libc::errno() }; + warn!("socket (host fd: {}) close failed: errno = {}", self.fd, errno); } } } impl File for SocketFile { fn read(&self, buf: &mut [u8]) -> Result { - let ret = unsafe { libc::ocall::read(self.fd, buf.as_mut_ptr() as *mut c_void, buf.len()) }; - if ret < 0 { - errno!(Errno::from_retval(unsafe { libc::errno() }), "") - } else { - Ok(ret as usize) - } + let ret = try_libc!(libc::ocall::read(self.fd, buf.as_mut_ptr() as *mut c_void, buf.len())); + Ok(ret as usize) } fn write(&self, buf: &[u8]) -> Result { - let ret = unsafe { libc::ocall::write(self.fd, buf.as_ptr() as *const c_void, buf.len()) }; - if ret < 0 { - errno!(Errno::from_retval(unsafe { libc::errno() }), "") - } else { - Ok(ret as usize) - } + let ret = try_libc!(libc::ocall::write(self.fd, buf.as_ptr() as *const c_void, buf.len())); + Ok(ret as usize) } fn read_at(&self, _offset: usize, buf: &mut [u8]) -> Result { diff --git a/src/libos/src/prelude.rs b/src/libos/src/prelude.rs index 113b3b5c..74235313 100644 --- a/src/libos/src/prelude.rs +++ b/src/libos/src/prelude.rs @@ -35,7 +35,7 @@ macro_rules! debug_trace { } macro_rules! errno { - ($errno: expr, $msg: expr) => {{ + ($errno: ident, $msg: expr) => {{ println!( "ERROR: {} ({}, line {} in file {})", $errno, @@ -47,6 +47,25 @@ macro_rules! errno { }}; } +// return Err(errno) if libc return -1 +macro_rules! try_libc { + ($ret: expr) => {{ + let ret = unsafe { $ret }; + if ret == -1 { + let errno = unsafe { libc::errno() }; + // println will cause libc ocall and overwrite errno + println!( + "ERROR from libc: {} (line {} in file {})", + errno, + line!(), + file!() + ); + return Err(Error::new(Errno::from_errno(errno), "libc error")); + } + ret + }}; +} + pub fn align_up(addr: usize, align: usize) -> usize { (addr + (align - 1)) / align * align } diff --git a/src/libos/src/syscall/mod.rs b/src/libos/src/syscall/mod.rs index 927c5678..9d37531e 100644 --- a/src/libos/src/syscall/mod.rs +++ b/src/libos/src/syscall/mod.rs @@ -941,10 +941,7 @@ fn do_connect( let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?; let socket = file_ref.as_socket()?; - let ret = unsafe { libc::ocall::connect(socket.fd(), addr, addr_len) }; - if ret < 0 { - return errno!(Errno::from_retval(unsafe { libc::errno() }), ""); - } + let ret = try_libc!(libc::ocall::connect(socket.fd(), addr, addr_len)); Ok(ret as isize) } @@ -977,10 +974,7 @@ fn do_shutdown(fd: c_int, how: c_int) -> Result { let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?; let socket = file_ref.as_socket()?; - let ret = unsafe { libc::ocall::shutdown(socket.fd(), how) }; - if ret < 0 { - return errno!(Errno::from_retval(unsafe { libc::errno() }), ""); - } + let ret = try_libc!(libc::ocall::shutdown(socket.fd(), how)); Ok(ret as isize) } @@ -995,10 +989,7 @@ fn do_bind( let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?; let socket = file_ref.as_socket()?; - let ret = unsafe { libc::ocall::bind(socket.fd(), addr, addr_len) }; - if ret < 0 { - return errno!(Errno::from_retval(unsafe { libc::errno() }), ""); - } + let ret = try_libc!(libc::ocall::bind(socket.fd(), addr, addr_len)); Ok(ret as isize) } @@ -1009,10 +1000,7 @@ fn do_listen(fd: c_int, backlog: c_int) -> Result { let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?; let socket = file_ref.as_socket()?; - let ret = unsafe { libc::ocall::listen(socket.fd(), backlog) }; - if ret < 0 { - return errno!(Errno::from_retval(unsafe { libc::errno() }), ""); - } + let ret = try_libc!(libc::ocall::listen(socket.fd(), backlog)); Ok(ret as isize) } @@ -1032,10 +1020,13 @@ fn do_setsockopt( let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?; let socket = file_ref.as_socket()?; - let ret = unsafe { libc::ocall::setsockopt(socket.fd(), level, optname, optval, optlen) }; - if ret < 0 { - return errno!(Errno::from_retval(unsafe { libc::errno() }), ""); - } + let ret = try_libc!(libc::ocall::setsockopt( + socket.fd(), + level, + optname, + optval, + optlen + )); Ok(ret as isize) } @@ -1055,10 +1046,13 @@ fn do_getsockopt( let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?; let socket = file_ref.as_socket()?; - let ret = unsafe { libc::ocall::getsockopt(socket.fd(), level, optname, optval, optlen) }; - if ret < 0 { - return errno!(Errno::from_retval(unsafe { libc::errno() }), ""); - } + let ret = try_libc!(libc::ocall::getsockopt( + socket.fd(), + level, + optname, + optval, + optlen + )); Ok(ret as isize) } @@ -1079,10 +1073,14 @@ fn do_sendto( let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?; let socket = file_ref.as_socket()?; - let ret = unsafe { libc::ocall::sendto(socket.fd(), base, len, flags, addr, addr_len) }; - if ret < 0 { - return errno!(Errno::from_retval(unsafe { libc::errno() }), ""); - } + let ret = try_libc!(libc::ocall::sendto( + socket.fd(), + base, + len, + flags, + addr, + addr_len + )); Ok(ret as isize) } @@ -1103,10 +1101,14 @@ fn do_recvfrom( let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?; let socket = file_ref.as_socket()?; - let ret = unsafe { libc::ocall::recvfrom(socket.fd(), base, len, flags, addr, addr_len) }; - if ret < 0 { - return errno!(Errno::from_retval(unsafe { libc::errno() }), ""); - } + let ret = try_libc!(libc::ocall::recvfrom( + socket.fd(), + base, + len, + flags, + addr, + addr_len + )); Ok(ret as isize) }