diff --git a/Cargo.lock b/Cargo.lock index 06b09c3c6..7bd3c09b4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1073,7 +1073,7 @@ version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df1d1bc1084549d60725ccc53a2bfa07f67fe4689fda07b05a36531f2988104a" dependencies = [ - "nix", + "nix 0.23.1", "winapi", ] @@ -1177,6 +1177,18 @@ dependencies = [ "memoffset", ] +[[package]] +name = "nix" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "195cdbc1741b8134346d515b3a56a1c94b0912758009cfd53f99ea0f57b065fc" +dependencies = [ + "bitflags", + "cfg-if", + "libc", + "memoffset", +] + [[package]] name = "num-bigint" version = "0.4.3" @@ -1891,7 +1903,7 @@ dependencies = [ "memchr", "memmap2", "mt19937", - "nix", + "nix 0.24.2", "num-bigint", "num-complex", "num-integer", @@ -1962,7 +1974,7 @@ dependencies = [ "log", "memchr", "memoffset", - "nix", + "nix 0.24.2", "num-bigint", "num-complex", "num-integer", @@ -2036,9 +2048,9 @@ checksum = "61b3909d758bb75c79f23d4736fac9433868679d3ad2ea7a61e3c25cfda9a088" [[package]] name = "rustyline" -version = "9.1.2" +version = "10.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db7826789c0e25614b03e5a54a0717a86f9ff6e6e5247f92b369472869320039" +checksum = "1d1cd5ae51d3f7bf65d7969d579d502168ef578f289452bd8ccc91de28fda20e" dependencies = [ "bitflags", "cfg-if", @@ -2048,10 +2060,9 @@ dependencies = [ "libc", "log", "memchr", - "nix", + "nix 0.24.2", "radix_trie", "scopeguard", - "smallvec", "unicode-segmentation", "unicode-width", "utf8parse", diff --git a/Cargo.toml b/Cargo.toml index f5c39bd1f..eed94cbd8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -49,7 +49,7 @@ flame = { version = "0.2.2", optional = true } flamescope = { version = "0.1.2", optional = true } [target.'cfg(not(target_arch = "wasm32"))'.dependencies] -rustyline = "9.1.2" +rustyline = "10.0.0" [dev-dependencies] cpython = "0.7.0" diff --git a/src/shell.rs b/src/shell.rs index d7a548bf4..859ced498 100644 --- a/src/shell.rs +++ b/src/shell.rs @@ -112,10 +112,6 @@ pub fn run_shell(vm: &VirtualMachine, scope: Scope) -> PyResult<()> { ReadlineResult::Eof => { break; } - ReadlineResult::EncodingError => { - eprintln!("Invalid UTF-8 entered"); - Ok(()) - } ReadlineResult::Other(err) => { eprintln!("Readline error: {:?}", err); break; diff --git a/stdlib/Cargo.toml b/stdlib/Cargo.toml index aab0ed5ae..a80ae7998 100644 --- a/stdlib/Cargo.toml +++ b/stdlib/Cargo.toml @@ -56,7 +56,7 @@ base64 = "0.13.0" csv-core = "0.1.10" hex = "0.4.3" puruspe = "0.1.5" -nix = "0.23.1" +nix = "0.24" xml-rs = "0.8.4" libc = "0.2.126" cfg-if = "1.0.0" diff --git a/stdlib/src/socket.rs b/stdlib/src/socket.rs index 8954a8509..0c3070e8b 100644 --- a/stdlib/src/socket.rs +++ b/stdlib/src/socket.rs @@ -738,72 +738,6 @@ mod _socket { .map(|sock| sock as RawSocket) } - #[cfg(unix)] - mod nullable_socket { - use super::*; - use std::os::unix::io::AsRawFd; - - #[derive(Debug)] - #[repr(transparent)] - pub struct NullableSocket(Option); - impl From for NullableSocket { - fn from(sock: socket2::Socket) -> Self { - NullableSocket(Some(sock)) - } - } - impl NullableSocket { - pub fn invalid() -> Self { - Self(None) - } - pub fn get(&self) -> Option<&socket2::Socket> { - self.0.as_ref() - } - pub fn fd(&self) -> RawSocket { - self.get().map_or(INVALID_SOCKET, |sock| sock.as_raw_fd()) - } - pub fn insert(&mut self, sock: socket2::Socket) -> &mut socket2::Socket { - self.0.insert(sock) - } - } - } - #[cfg(windows)] - mod nullable_socket { - use super::*; - use std::os::windows::io::{AsRawSocket, FromRawSocket}; - - // TODO: may change if windows changes its TcpStream repr - #[derive(Debug)] - #[repr(transparent)] - pub struct NullableSocket(socket2::Socket); - impl From for NullableSocket { - fn from(sock: socket2::Socket) -> Self { - NullableSocket(sock) - } - } - impl NullableSocket { - pub fn invalid() -> Self { - // TODO: may become UB in the future; maybe see rust-lang/rust#74699 - Self(unsafe { socket2::Socket::from_raw_socket(INVALID_SOCKET) }) - } - pub fn get(&self) -> Option<&socket2::Socket> { - (self.0.as_raw_socket() != INVALID_SOCKET).then(|| &self.0) - } - pub fn fd(&self) -> RawSocket { - self.0.as_raw_socket() - } - pub fn insert(&mut self, sock: socket2::Socket) -> &mut socket2::Socket { - self.0 = sock; - &mut self.0 - } - } - } - use nullable_socket::NullableSocket; - impl Default for NullableSocket { - fn default() -> Self { - Self::invalid() - } - } - #[pyattr(name = "socket")] #[pyattr(name = "SocketType")] #[pyclass(name = "socket")] @@ -813,9 +747,11 @@ mod _socket { family: AtomicCell, proto: AtomicCell, pub(crate) timeout: AtomicCell, - sock: PyRwLock, + sock: PyRwLock>, } + const _: () = assert!(std::mem::size_of::>() == std::mem::size_of::()); + impl Default for PySocket { fn default() -> Self { PySocket { @@ -823,7 +759,7 @@ mod _socket { family: AtomicCell::default(), proto: AtomicCell::default(), timeout: AtomicCell::new(-1.0), - sock: PyRwLock::new(NullableSocket::invalid()), + sock: PyRwLock::new(None), } } } @@ -850,7 +786,7 @@ mod _socket { impl PySocket { pub fn sock_opt(&self) -> Option> { - PyRwLockReadGuard::try_map(self.sock.read(), |sock| sock.get()).ok() + PyRwLockReadGuard::try_map(self.sock.read(), |sock| sock.as_ref()).ok() } pub fn sock(&self) -> io::Result> { @@ -1406,13 +1342,16 @@ mod _socket { #[pymethod] #[inline] fn detach(&self) -> RawSocket { - let sock = std::mem::replace(&mut *self.sock.write(), NullableSocket::invalid()); - std::mem::ManuallyDrop::new(sock).fd() + let sock = self.sock.write().take(); + sock.map_or(INVALID_SOCKET, into_sock_fileno) } #[pymethod] fn fileno(&self) -> RawSocket { - self.sock.read().fd() + self.sock + .read() + .as_ref() + .map_or(INVALID_SOCKET, sock_fileno) } #[pymethod] @@ -1465,15 +1404,16 @@ mod _socket { name: i32, buflen: OptionalArg, vm: &VirtualMachine, - ) -> PyResult { - let fd = self.sock.read().fd() as _; + ) -> Result { + let sock = self.sock()?; + let fd = sock_fileno(&sock); let buflen = buflen.unwrap_or(0); if buflen == 0 { let mut flag: libc::c_int = 0; let mut flagsize = std::mem::size_of::() as _; let ret = unsafe { c::getsockopt( - fd, + fd as _, level, name, &mut flag as *mut libc::c_int as *mut _, @@ -1481,22 +1421,30 @@ mod _socket { ) }; if ret < 0 { - return Err(crate::vm::stdlib::os::errno_err(vm)); + return Err(crate::common::os::errno().into()); } Ok(vm.ctx.new_int(flag).into()) } else { if buflen <= 0 || buflen > 1024 { - return Err(vm.new_os_error("getsockopt buflen out of range".to_owned())); + return Err(vm + .new_os_error("getsockopt buflen out of range".to_owned()) + .into()); } let mut buf = vec![0u8; buflen as usize]; let mut buflen = buflen as _; let ret = unsafe { - c::getsockopt(fd, level, name, buf.as_mut_ptr() as *mut _, &mut buflen) + c::getsockopt( + fd as _, + level, + name, + buf.as_mut_ptr() as *mut _, + &mut buflen, + ) }; - buf.truncate(buflen as usize); if ret < 0 { - return Err(crate::vm::stdlib::os::errno_err(vm)); + return Err(crate::common::os::errno().into()); } + buf.truncate(buflen as usize); Ok(vm.ctx.new_bytes(buf).into()) } } @@ -1509,15 +1457,16 @@ mod _socket { value: Option>, optlen: OptionalArg, vm: &VirtualMachine, - ) -> PyResult<()> { - let fd = self.sock.read().fd() as _; + ) -> Result<(), IoOrPyException> { + let sock = self.sock()?; + let fd = sock_fileno(&sock); let ret = match (value, optlen) { (Some(Either::A(b)), OptionalArg::Missing) => b.with_ref(|b| unsafe { - c::setsockopt(fd, level, name, b.as_ptr() as *const _, b.len() as _) + c::setsockopt(fd as _, level, name, b.as_ptr() as *const _, b.len() as _) }), (Some(Either::B(ref val)), OptionalArg::Missing) => unsafe { c::setsockopt( - fd, + fd as _, level, name, val as *const i32 as *const _, @@ -1525,16 +1474,16 @@ mod _socket { ) }, (None, OptionalArg::Present(optlen)) => unsafe { - c::setsockopt(fd, level, name, std::ptr::null(), optlen as _) + c::setsockopt(fd as _, level, name, std::ptr::null(), optlen as _) }, _ => { - return Err( - vm.new_type_error("expected the value arg xor the optlen arg".to_owned()) - ); + return Err(vm + .new_type_error("expected the value arg xor the optlen arg".to_owned()) + .into()); } }; if ret < 0 { - Err(crate::vm::stdlib::os::errno_err(vm)) + Err(crate::common::os::errno().into()) } else { Ok(()) } @@ -1573,7 +1522,7 @@ mod _socket { format!( "", // cast because INVALID_SOCKET is unsigned, so would show usize::MAX instead of -1 - self.sock.read().fd() as i64, + self.fileno() as i64, self.family.load(), self.kind.load(), self.proto.load(), @@ -2135,7 +2084,7 @@ mod _socket { fn if_nameindex(vm: &VirtualMachine) -> PyResult> { #[cfg(not(windows))] { - let list = if_nameindex() + let list = nix::net::if_::if_nameindex() .map_err(|err| err.into_pyexception(vm))? .to_slice() .iter() @@ -2146,55 +2095,7 @@ mod _socket { }) .collect(); - return Ok(list); - - // all the stuff below should be in nix soon, hopefully - - use ffi::CStr; - use std::ptr::NonNull; - - #[repr(transparent)] - struct Interface(libc::if_nameindex); - - impl Interface { - fn index(&self) -> libc::c_uint { - self.0.if_index - } - fn name(&self) -> &CStr { - unsafe { CStr::from_ptr(self.0.if_name) } - } - } - - struct Interfaces { - ptr: NonNull, - } - - impl Interfaces { - fn to_slice(&self) -> &[Interface] { - let ifs = self.ptr.as_ptr() as *const Interface; - let mut len = 0; - unsafe { - while (*ifs.add(len)).0.if_index != 0 { - len += 1 - } - std::slice::from_raw_parts(ifs, len) - } - } - } - - impl Drop for Interfaces { - fn drop(&mut self) { - unsafe { libc::if_freenameindex(self.ptr.as_ptr()) }; - } - } - - fn if_nameindex() -> nix::Result { - unsafe { - let ifs = libc::if_nameindex(); - let ptr = NonNull::new(ifs).ok_or_else(nix::Error::last)?; - Ok(Interfaces { ptr }) - } - } + Ok(list) } #[cfg(windows)] { diff --git a/vm/Cargo.toml b/vm/Cargo.toml index 7e15ab842..d4a94a413 100644 --- a/vm/Cargo.toml +++ b/vm/Cargo.toml @@ -50,7 +50,7 @@ indexmap = "1.8.1" ahash = "0.7.6" bitflags = "1.3.2" libc = "0.2.126" -nix = "0.23.1" +nix = "0.24.2" paste = "1.0.7" is-macro = "0.2.0" result-like = "0.4.5" @@ -101,7 +101,7 @@ strum = "0.24.0" strum_macros = "0.24.0" [target.'cfg(not(target_arch = "wasm32"))'.dependencies] -rustyline = "9" +rustyline = "10.0.0" which = "4.2.5" [target.'cfg(any(not(target_arch = "wasm32"), target_os = "wasi"))'.dependencies] diff --git a/vm/src/readline.rs b/vm/src/readline.rs index 413d30e7c..4e3db463b 100644 --- a/vm/src/readline.rs +++ b/vm/src/readline.rs @@ -8,7 +8,6 @@ pub enum ReadlineResult { Eof, Interrupt, Io(std::io::Error), - EncodingError, Other(OtherError), } @@ -51,11 +50,8 @@ mod basic_readline { match next_line { Some(Ok(line)) => ReadlineResult::Line(line), None => ReadlineResult::Eof, - Some(Err(e)) => match e.kind() { - io::ErrorKind::Interrupted => ReadlineResult::Interrupt, - io::ErrorKind::InvalidData => ReadlineResult::EncodingError, - _ => ReadlineResult::Io(e), - }, + Some(Err(e)) if e.kind() == io::ErrorKind::Interrupted => ReadlineResult::Interrupt, + Some(Err(e)) => ReadlineResult::Io(e), } } } @@ -82,7 +78,8 @@ mod rustyline_readline { .tab_stop(8) .bracketed_paste(false) // multi-line paste .build(), - ); + ) + .expect("failed to initialize line editor"); repl.set_helper(Some(helper)); Readline { repl } } @@ -109,16 +106,15 @@ mod rustyline_readline { pub fn readline(&mut self, prompt: &str) -> ReadlineResult { use rustyline::error::ReadlineError; - match self.repl.readline(prompt) { - Ok(line) => ReadlineResult::Line(line), - Err(ReadlineError::Interrupted) => ReadlineResult::Interrupt, - Err(ReadlineError::Eof) => ReadlineResult::Eof, - Err(ReadlineError::Io(e)) => ReadlineResult::Io(e), - #[cfg(unix)] - Err(ReadlineError::Utf8Error) => ReadlineResult::EncodingError, - #[cfg(windows)] - Err(ReadlineError::Decode(_)) => ReadlineResult::EncodingError, - Err(e) => ReadlineResult::Other(e.into()), + loop { + break match self.repl.readline(prompt) { + Ok(line) => ReadlineResult::Line(line), + Err(ReadlineError::Interrupted) => ReadlineResult::Interrupt, + Err(ReadlineError::Eof) => ReadlineResult::Eof, + Err(ReadlineError::Io(e)) => ReadlineResult::Io(e), + Err(ReadlineError::WindowResized) => continue, + Err(e) => ReadlineResult::Other(e.into()), + }; } } } diff --git a/vm/src/stdlib/builtins.rs b/vm/src/stdlib/builtins.rs index f6154642c..a422c2959 100644 --- a/vm/src/stdlib/builtins.rs +++ b/vm/src/stdlib/builtins.rs @@ -408,9 +408,6 @@ mod builtins { Err(vm.new_exception_empty(vm.ctx.exceptions.keyboard_interrupt.to_owned())) } ReadlineResult::Io(e) => Err(vm.new_os_error(e.to_string())), - ReadlineResult::EncodingError => { - Err(vm.new_unicode_decode_error("Error decoding readline input".to_owned())) - } ReadlineResult::Other(e) => Err(vm.new_runtime_error(e.to_string())), } } else {