diff options
| author | bors <bors@rust-lang.org> | 2018-11-15 12:43:01 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2018-11-15 12:43:01 +0000 |
| commit | 9649c1f70fddd01843024932df97fb5a2b10bfe8 (patch) | |
| tree | bc6af666244208eb4354636428ac26731935cbdc /src/libstd | |
| parent | 99e3fca27d141e2d100ebaf5d5a4104234ae201a (diff) | |
| parent | d0e08ce88e0926e8e2bc393d3d7982fd767f37b8 (diff) | |
| download | rust-9649c1f70fddd01843024932df97fb5a2b10bfe8.tar.gz rust-9649c1f70fddd01843024932df97fb5a2b10bfe8.zip | |
Auto merge of #55974 - pietroalbini:rollup, r=pietroalbini
Rollup of 17 pull requests Successful merges: - #55182 (Redox: Update to new changes) - #55211 (Add BufWriter::buffer method) - #55507 (Add link to std::mem::size_of to size_of intrinsic documentation) - #55530 (Speed up String::from_utf16) - #55556 (Use `Mmap` to open the rmeta file.) - #55622 (NetBSD: link libstd with librt in addition to libpthread) - #55750 (Make `NodeId` and `HirLocalId` `newtype_index`) - #55778 (Wrap some query results in `Lrc`.) - #55781 (More precise spans for temps and their drops) - #55785 (Add mem::forget_unsized() for forgetting unsized values) - #55852 (Rewrite `...` as `..=` as a `MachineApplicable` 2018 idiom lint) - #55865 (Unix RwLock: avoid racy access to write_locked) - #55901 (fix various typos in doc comments) - #55926 (Change sidebar selector to fix compatibility with docs.rs) - #55930 (A handful of hir tweaks) - #55932 (core/char: Speed up `to_digit()` for `radix <= 10`) - #55956 (add tests for some fixed ICEs) Failed merges: r? @ghost
Diffstat (limited to 'src/libstd')
| -rw-r--r-- | src/libstd/alloc.rs | 2 | ||||
| -rw-r--r-- | src/libstd/build.rs | 5 | ||||
| -rw-r--r-- | src/libstd/collections/hash/map.rs | 2 | ||||
| -rw-r--r-- | src/libstd/io/buffered.rs | 48 | ||||
| -rw-r--r-- | src/libstd/keyword_docs.rs | 2 | ||||
| -rw-r--r-- | src/libstd/net/ip.rs | 2 | ||||
| -rw-r--r-- | src/libstd/process.rs | 4 | ||||
| -rw-r--r-- | src/libstd/sys/redox/fd.rs | 2 | ||||
| -rw-r--r-- | src/libstd/sys/redox/mod.rs | 23 | ||||
| -rw-r--r-- | src/libstd/sys/redox/os.rs | 101 | ||||
| -rw-r--r-- | src/libstd/sys/redox/process.rs | 115 | ||||
| -rw-r--r-- | src/libstd/sys/redox/syscall/call.rs | 17 | ||||
| -rw-r--r-- | src/libstd/sys/redox/syscall/flag.rs | 44 | ||||
| -rw-r--r-- | src/libstd/sys/redox/syscall/number.rs | 2 | ||||
| -rw-r--r-- | src/libstd/sys/unix/fd.rs | 2 | ||||
| -rw-r--r-- | src/libstd/sys/unix/rwlock.rs | 6 | ||||
| -rw-r--r-- | src/libstd/thread/mod.rs | 2 |
17 files changed, 291 insertions, 88 deletions
diff --git a/src/libstd/alloc.rs b/src/libstd/alloc.rs index 9c057396470..b024574427e 100644 --- a/src/libstd/alloc.rs +++ b/src/libstd/alloc.rs @@ -85,7 +85,7 @@ pub use alloc_crate::alloc::*; /// This is based on `malloc` on Unix platforms and `HeapAlloc` on Windows, /// plus related functions. /// -/// This type implements the `GlobalAlloc` trait and Rust programs by deafult +/// This type implements the `GlobalAlloc` trait and Rust programs by default /// work as if they had this definition: /// /// ```rust diff --git a/src/libstd/build.rs b/src/libstd/build.rs index b3851d22841..9d6e8c4cafd 100644 --- a/src/libstd/build.rs +++ b/src/libstd/build.rs @@ -41,8 +41,11 @@ fn main() { } else if target.contains("freebsd") { println!("cargo:rustc-link-lib=execinfo"); println!("cargo:rustc-link-lib=pthread"); + } else if target.contains("netbsd") { + println!("cargo:rustc-link-lib=pthread"); + println!("cargo:rustc-link-lib=rt"); } else if target.contains("dragonfly") || target.contains("bitrig") || - target.contains("netbsd") || target.contains("openbsd") { + target.contains("openbsd") { println!("cargo:rustc-link-lib=pthread"); } else if target.contains("solaris") { println!("cargo:rustc-link-lib=socket"); diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 8de415e8aed..bb2f152edc6 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -1569,7 +1569,7 @@ impl<K, V, S> HashMap<K, V, S> /// where the key should go, meaning the keys may become "lost" if their /// location does not reflect their state. For instance, if you change a key /// so that the map now contains keys which compare equal, search may start - /// acting eratically, with two keys randomly masking eachother. Implementations + /// acting erratically, with two keys randomly masking each other. Implementations /// are free to assume this doesn't happen (within the limits of memory-safety). #[unstable(feature = "hash_raw_entry", issue = "54043")] pub fn raw_entry_mut(&mut self) -> RawEntryBuilderMut<K, V, S> { diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index e26e6d391f8..476ee3f71ca 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -525,6 +525,25 @@ impl<W: Write> BufWriter<W> { #[stable(feature = "rust1", since = "1.0.0")] pub fn get_mut(&mut self) -> &mut W { self.inner.as_mut().unwrap() } + /// Returns a reference to the internally buffered data. + /// + /// # Examples + /// + /// ```no_run + /// # #![feature(bufreader_buffer)] + /// use std::io::BufWriter; + /// use std::net::TcpStream; + /// + /// let buf_writer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap()); + /// + /// // See how many bytes are currently buffered + /// let bytes_buffered = buf_writer.buffer().len(); + /// ``` + #[unstable(feature = "bufreader_buffer", issue = "45323")] + pub fn buffer(&self) -> &[u8] { + &self.buf + } + /// Unwraps this `BufWriter`, returning the underlying writer. /// /// The buffer is written out before returning the writer. @@ -965,31 +984,31 @@ mod tests { let mut buf = [0, 0, 0]; let nread = reader.read(&mut buf); assert_eq!(nread.unwrap(), 3); - let b: &[_] = &[5, 6, 7]; - assert_eq!(buf, b); + assert_eq!(buf, [5, 6, 7]); + assert_eq!(reader.buffer(), []); let mut buf = [0, 0]; let nread = reader.read(&mut buf); assert_eq!(nread.unwrap(), 2); - let b: &[_] = &[0, 1]; - assert_eq!(buf, b); + assert_eq!(buf, [0, 1]); + assert_eq!(reader.buffer(), []); let mut buf = [0]; let nread = reader.read(&mut buf); assert_eq!(nread.unwrap(), 1); - let b: &[_] = &[2]; - assert_eq!(buf, b); + assert_eq!(buf, [2]); + assert_eq!(reader.buffer(), [3]); let mut buf = [0, 0, 0]; let nread = reader.read(&mut buf); assert_eq!(nread.unwrap(), 1); - let b: &[_] = &[3, 0, 0]; - assert_eq!(buf, b); + assert_eq!(buf, [3, 0, 0]); + assert_eq!(reader.buffer(), []); let nread = reader.read(&mut buf); assert_eq!(nread.unwrap(), 1); - let b: &[_] = &[4, 0, 0]; - assert_eq!(buf, b); + assert_eq!(buf, [4, 0, 0]); + assert_eq!(reader.buffer(), []); assert_eq!(reader.read(&mut buf).unwrap(), 0); } @@ -1078,31 +1097,40 @@ mod tests { let mut writer = BufWriter::with_capacity(2, inner); writer.write(&[0, 1]).unwrap(); + assert_eq!(writer.buffer(), []); assert_eq!(*writer.get_ref(), [0, 1]); writer.write(&[2]).unwrap(); + assert_eq!(writer.buffer(), [2]); assert_eq!(*writer.get_ref(), [0, 1]); writer.write(&[3]).unwrap(); + assert_eq!(writer.buffer(), [2, 3]); assert_eq!(*writer.get_ref(), [0, 1]); writer.flush().unwrap(); + assert_eq!(writer.buffer(), []); assert_eq!(*writer.get_ref(), [0, 1, 2, 3]); writer.write(&[4]).unwrap(); writer.write(&[5]).unwrap(); + assert_eq!(writer.buffer(), [4, 5]); assert_eq!(*writer.get_ref(), [0, 1, 2, 3]); writer.write(&[6]).unwrap(); + assert_eq!(writer.buffer(), [6]); assert_eq!(*writer.get_ref(), [0, 1, 2, 3, 4, 5]); writer.write(&[7, 8]).unwrap(); + assert_eq!(writer.buffer(), []); assert_eq!(*writer.get_ref(), [0, 1, 2, 3, 4, 5, 6, 7, 8]); writer.write(&[9, 10, 11]).unwrap(); + assert_eq!(writer.buffer(), []); assert_eq!(*writer.get_ref(), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]); writer.flush().unwrap(); + assert_eq!(writer.buffer(), []); assert_eq!(*writer.get_ref(), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]); } diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs index 6c95854c66c..13cf3133dcd 100644 --- a/src/libstd/keyword_docs.rs +++ b/src/libstd/keyword_docs.rs @@ -615,7 +615,7 @@ mod loop_keyword { } // /// The keyword used to define structs. /// -/// Structs in Rust come in three flavours: Structs with named fields, tuple structs, and unit +/// Structs in Rust come in three flavors: Structs with named fields, tuple structs, and unit /// structs. /// /// ```rust diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index 2517c45696a..8685cb73887 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -852,7 +852,7 @@ impl From<[u8; 4]> for IpAddr { impl Ipv6Addr { /// Creates a new IPv6 address from eight 16-bit segments. /// - /// The result will represent the IP address a:b:c:d:e:f:g:h. + /// The result will represent the IP address `a:b:c:d:e:f:g:h`. /// /// # Examples /// diff --git a/src/libstd/process.rs b/src/libstd/process.rs index 327ad7f64c2..51481e129df 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -1122,7 +1122,7 @@ impl From<fs::File> for Stdio { /// let file = File::open("foo.txt").unwrap(); /// /// let reverse = Command::new("rev") - /// .stdin(file) // Implicit File convertion into a Stdio + /// .stdin(file) // Implicit File conversion into a Stdio /// .output() /// .expect("failed reverse command"); /// @@ -1340,7 +1340,7 @@ impl Child { /// Attempts to collect the exit status of the child if it has already /// exited. /// - /// This function will not block the calling thread and will only advisorily + /// This function will not block the calling thread and will only /// check to see if the child process has exited or not. If the child has /// exited then on Unix the process id is reaped. This function is /// guaranteed to repeatedly return a successful exit status so long as the diff --git a/src/libstd/sys/redox/fd.rs b/src/libstd/sys/redox/fd.rs index d61103a872f..d62b09134bb 100644 --- a/src/libstd/sys/redox/fd.rs +++ b/src/libstd/sys/redox/fd.rs @@ -26,7 +26,7 @@ impl FileDesc { pub fn raw(&self) -> usize { self.fd } - /// Extracts the actual filedescriptor without closing it. + /// Extracts the actual file descriptor without closing it. pub fn into_raw(self) -> usize { let fd = self.fd; mem::forget(self); diff --git a/src/libstd/sys/redox/mod.rs b/src/libstd/sys/redox/mod.rs index edb407ecd23..3543d8f8fa3 100644 --- a/src/libstd/sys/redox/mod.rs +++ b/src/libstd/sys/redox/mod.rs @@ -77,6 +77,29 @@ pub fn cvt(result: Result<usize, syscall::Error>) -> io::Result<usize> { result.map_err(|err| io::Error::from_raw_os_error(err.errno)) } +#[doc(hidden)] +pub trait IsMinusOne { + fn is_minus_one(&self) -> bool; +} + +macro_rules! impl_is_minus_one { + ($($t:ident)*) => ($(impl IsMinusOne for $t { + fn is_minus_one(&self) -> bool { + *self == -1 + } + })*) +} + +impl_is_minus_one! { i8 i16 i32 i64 isize } + +pub fn cvt_libc<T: IsMinusOne>(t: T) -> io::Result<T> { + if t.is_minus_one() { + Err(io::Error::last_os_error()) + } else { + Ok(t) + } +} + /// On Redox, use an illegal instruction to abort pub unsafe fn abort_internal() -> ! { ::core::intrinsics::abort(); diff --git a/src/libstd/sys/redox/os.rs b/src/libstd/sys/redox/os.rs index 5822216779b..84eb56615b6 100644 --- a/src/libstd/sys/redox/os.rs +++ b/src/libstd/sys/redox/os.rs @@ -12,10 +12,12 @@ #![allow(unused_imports)] // lots of cfg code here +use libc::{self, c_char}; + use os::unix::prelude::*; use error::Error as StdError; -use ffi::{OsString, OsStr}; +use ffi::{CStr, CString, OsStr, OsString}; use fmt; use io::{self, Read, Write}; use iter; @@ -27,7 +29,7 @@ use ptr; use slice; use str; use sys_common::mutex::Mutex; -use sys::{cvt, fd, syscall}; +use sys::{cvt, cvt_libc, fd, syscall}; use vec; extern { @@ -129,6 +131,8 @@ pub fn current_exe() -> io::Result<PathBuf> { Ok(PathBuf::from(path)) } +pub static ENV_LOCK: Mutex = Mutex::new(); + pub struct Env { iter: vec::IntoIter<(OsString, OsString)>, _dont_send_or_sync_me: PhantomData<*mut ()>, @@ -140,52 +144,83 @@ impl Iterator for Env { fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() } } +pub unsafe fn environ() -> *mut *const *const c_char { + extern { static mut environ: *const *const c_char; } + &mut environ +} + /// Returns a vector of (variable, value) byte-vector pairs for all the /// environment variables of the current process. pub fn env() -> Env { - let mut variables: Vec<(OsString, OsString)> = Vec::new(); - if let Ok(mut file) = ::fs::File::open("env:") { - let mut string = String::new(); - if file.read_to_string(&mut string).is_ok() { - for line in string.lines() { - let mut parts = line.splitn(2, '='); - if let Some(name) = parts.next() { - let value = parts.next().unwrap_or(""); - variables.push((OsString::from(name.to_string()), - OsString::from(value.to_string()))); - } + unsafe { + let _guard = ENV_LOCK.lock(); + let mut environ = *environ(); + if environ == ptr::null() { + panic!("os::env() failure getting env string from OS: {}", + io::Error::last_os_error()); + } + let mut result = Vec::new(); + while *environ != ptr::null() { + if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) { + result.push(key_value); } + environ = environ.offset(1); + } + return Env { + iter: result.into_iter(), + _dont_send_or_sync_me: PhantomData, + } + } + + fn parse(input: &[u8]) -> Option<(OsString, OsString)> { + // Strategy (copied from glibc): Variable name and value are separated + // by an ASCII equals sign '='. Since a variable name must not be + // empty, allow variable names starting with an equals sign. Skip all + // malformed lines. + if input.is_empty() { + return None; } + let pos = memchr::memchr(b'=', &input[1..]).map(|p| p + 1); + pos.map(|p| ( + OsStringExt::from_vec(input[..p].to_vec()), + OsStringExt::from_vec(input[p+1..].to_vec()), + )) } - Env { iter: variables.into_iter(), _dont_send_or_sync_me: PhantomData } } -pub fn getenv(key: &OsStr) -> io::Result<Option<OsString>> { - if ! key.is_empty() { - if let Ok(mut file) = ::fs::File::open(&("env:".to_owned() + key.to_str().unwrap())) { - let mut string = String::new(); - file.read_to_string(&mut string)?; - Ok(Some(OsString::from(string))) +pub fn getenv(k: &OsStr) -> io::Result<Option<OsString>> { + // environment variables with a nul byte can't be set, so their value is + // always None as well + let k = CString::new(k.as_bytes())?; + unsafe { + let _guard = ENV_LOCK.lock(); + let s = libc::getenv(k.as_ptr()) as *const libc::c_char; + let ret = if s.is_null() { + None } else { - Ok(None) - } - } else { - Ok(None) + Some(OsStringExt::from_vec(CStr::from_ptr(s).to_bytes().to_vec())) + }; + Ok(ret) } } -pub fn setenv(key: &OsStr, value: &OsStr) -> io::Result<()> { - if ! key.is_empty() { - let mut file = ::fs::File::create(&("env:".to_owned() + key.to_str().unwrap()))?; - file.write_all(value.as_bytes())?; - file.set_len(value.len() as u64)?; +pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { + let k = CString::new(k.as_bytes())?; + let v = CString::new(v.as_bytes())?; + + unsafe { + let _guard = ENV_LOCK.lock(); + cvt_libc(libc::setenv(k.as_ptr(), v.as_ptr(), 1)).map(|_| ()) } - Ok(()) } -pub fn unsetenv(key: &OsStr) -> io::Result<()> { - ::fs::remove_file(&("env:".to_owned() + key.to_str().unwrap()))?; - Ok(()) +pub fn unsetenv(n: &OsStr) -> io::Result<()> { + let nbuf = CString::new(n.as_bytes())?; + + unsafe { + let _guard = ENV_LOCK.lock(); + cvt_libc(libc::unsetenv(nbuf.as_ptr())).map(|_| ()) + } } pub fn page_size() -> usize { diff --git a/src/libstd/sys/redox/process.rs b/src/libstd/sys/redox/process.rs index 2037616e6ac..4370c1e0502 100644 --- a/src/libstd/sys/redox/process.rs +++ b/src/libstd/sys/redox/process.rs @@ -9,15 +9,19 @@ // except according to those terms. use env::{split_paths}; -use ffi::OsStr; -use os::unix::ffi::OsStrExt; +use ffi::{CStr, OsStr}; use fmt; -use io::{self, Error, ErrorKind}; -use iter; +use fs::File; +use io::{self, prelude::*, BufReader, Error, ErrorKind, SeekFrom}; use libc::{EXIT_SUCCESS, EXIT_FAILURE}; +use os::unix::ffi::OsStrExt; use path::{Path, PathBuf}; +use ptr; +use sys::ext::fs::MetadataExt; +use sys::ext::io::AsRawFd; use sys::fd::FileDesc; -use sys::fs::{File, OpenOptions}; +use sys::fs::{File as SysFile, OpenOptions}; +use sys::os::{ENV_LOCK, environ}; use sys::pipe::{self, AnonPipe}; use sys::{cvt, syscall}; use sys_common::process::{CommandEnv, DefaultEnvKey}; @@ -297,12 +301,6 @@ impl Command { t!(callback()); } - let args: Vec<[usize; 2]> = iter::once( - [self.program.as_ptr() as usize, self.program.len()] - ).chain( - self.args.iter().map(|arg| [arg.as_ptr() as usize, arg.len()]) - ).collect(); - self.env.apply(); let program = if self.program.contains(':') || self.program.contains('/') { @@ -321,14 +319,93 @@ impl Command { None }; - if let Some(program) = program { - if let Err(err) = syscall::execve(program.as_os_str().as_bytes(), &args) { - io::Error::from_raw_os_error(err.errno as i32) + let mut file = if let Some(program) = program { + t!(File::open(program.as_os_str())) + } else { + return io::Error::from_raw_os_error(syscall::ENOENT); + }; + + // Push all the arguments + let mut args: Vec<[usize; 2]> = Vec::with_capacity(1 + self.args.len()); + + let interpreter = { + let mut reader = BufReader::new(&file); + + let mut shebang = [0; 2]; + let mut read = 0; + loop { + match t!(reader.read(&mut shebang[read..])) { + 0 => break, + n => read += n, + } + } + + if &shebang == b"#!" { + // This is an interpreted script. + // First of all, since we'll be passing another file to + // fexec(), we need to manually check that we have permission + // to execute this file: + let uid = t!(cvt(syscall::getuid())); + let gid = t!(cvt(syscall::getgid())); + let meta = t!(file.metadata()); + + let mode = if uid == meta.uid() as usize { + meta.mode() >> 3*2 & 0o7 + } else if gid == meta.gid() as usize { + meta.mode() >> 3*1 & 0o7 + } else { + meta.mode() & 0o7 + }; + if mode & 1 == 0 { + return io::Error::from_raw_os_error(syscall::EPERM); + } + + // Second of all, we need to actually read which interpreter it wants + let mut interpreter = Vec::new(); + t!(reader.read_until(b'\n', &mut interpreter)); + // Pop one trailing newline, if any + if interpreter.ends_with(&[b'\n']) { + interpreter.pop().unwrap(); + } + + // FIXME: Here we could just reassign `file` directly, if it + // wasn't for lexical lifetimes. Remove the whole `let + // interpreter = { ... };` hack once NLL lands. + // NOTE: Although DO REMEMBER to make sure the interpreter path + // still lives long enough to reach fexec. + Some(interpreter) } else { - panic!("return from exec without err"); + None + } + }; + if let Some(ref interpreter) = interpreter { + let path: &OsStr = OsStr::from_bytes(&interpreter); + file = t!(File::open(path)); + + args.push([interpreter.as_ptr() as usize, interpreter.len()]); + } else { + t!(file.seek(SeekFrom::Start(0))); + } + + args.push([self.program.as_ptr() as usize, self.program.len()]); + args.extend(self.args.iter().map(|arg| [arg.as_ptr() as usize, arg.len()])); + + // Push all the variables + let mut vars: Vec<[usize; 2]> = Vec::new(); + { + let _guard = ENV_LOCK.lock(); + let mut environ = *environ(); + while *environ != ptr::null() { + let var = CStr::from_ptr(*environ).to_bytes(); + vars.push([var.as_ptr() as usize, var.len()]); + environ = environ.offset(1); } + } + + if let Err(err) = syscall::fexec(file.as_raw_fd(), &args, &vars) { + io::Error::from_raw_os_error(err.errno as i32) } else { - io::Error::from_raw_os_error(syscall::ENOENT) + panic!("return from exec without err"); } } @@ -392,7 +469,7 @@ impl Stdio { let mut opts = OpenOptions::new(); opts.read(readable); opts.write(!readable); - let fd = File::open(Path::new("null:"), &opts)?; + let fd = SysFile::open(Path::new("null:"), &opts)?; Ok((ChildStdio::Owned(fd.into_fd()), None)) } } @@ -405,8 +482,8 @@ impl From<AnonPipe> for Stdio { } } -impl From<File> for Stdio { - fn from(file: File) -> Stdio { +impl From<SysFile> for Stdio { + fn from(file: SysFile) -> Stdio { Stdio::Fd(file.into_fd()) } } diff --git a/src/libstd/sys/redox/syscall/call.rs b/src/libstd/sys/redox/syscall/call.rs index f9a8bd61ac8..577dde4b4be 100644 --- a/src/libstd/sys/redox/syscall/call.rs +++ b/src/libstd/sys/redox/syscall/call.rs @@ -45,7 +45,7 @@ pub unsafe fn brk(addr: usize) -> Result<usize> { /// # Errors /// /// * `EACCES` - permission is denied for one of the components of `path`, or `path` -/// * `EFAULT` - `path` does not point to the process's addressible memory +/// * `EFAULT` - `path` does not point to the process's addressable memory /// * `EIO` - an I/O error occurred /// * `ENOENT` - `path` does not exit /// * `ENOTDIR` - `path` is not a directory @@ -82,12 +82,6 @@ pub fn dup2(fd: usize, newfd: usize, buf: &[u8]) -> Result<usize> { unsafe { syscall4(SYS_DUP2, fd, newfd, buf.as_ptr() as usize, buf.len()) } } -/// Replace the current process with a new executable -pub fn execve<T: AsRef<[u8]>>(path: T, args: &[[usize; 2]]) -> Result<usize> { - unsafe { syscall4(SYS_EXECVE, path.as_ref().as_ptr() as usize, - path.as_ref().len(), args.as_ptr() as usize, args.len()) } -} - /// Exit the current process pub fn exit(status: usize) -> Result<usize> { unsafe { syscall1(SYS_EXIT, status) } @@ -110,9 +104,10 @@ pub fn fcntl(fd: usize, cmd: usize, arg: usize) -> Result<usize> { unsafe { syscall3(SYS_FCNTL, fd, cmd, arg) } } -/// Register a file for event-based I/O -pub fn fevent(fd: usize, flags: usize) -> Result<usize> { - unsafe { syscall2(SYS_FEVENT, fd, flags) } +/// Replace the current process with a new executable +pub fn fexec(fd: usize, args: &[[usize; 2]], vars: &[[usize; 2]]) -> Result<usize> { + unsafe { syscall5(SYS_FEXEC, fd, args.as_ptr() as usize, args.len(), + vars.as_ptr() as usize, vars.len()) } } /// Map a file into memory @@ -347,7 +342,7 @@ pub fn waitpid(pid: usize, status: &mut usize, options: usize) -> Result<usize> /// /// * `EAGAIN` - the file descriptor was opened with `O_NONBLOCK` and writing would block /// * `EBADF` - the file descriptor is not valid or is not open for writing -/// * `EFAULT` - `buf` does not point to the process's addressible memory +/// * `EFAULT` - `buf` does not point to the process's addressable memory /// * `EIO` - an I/O error occurred /// * `ENOSPC` - the device containing the file descriptor has no room for data /// * `EPIPE` - the file descriptor refers to a pipe or socket whose reading end is closed diff --git a/src/libstd/sys/redox/syscall/flag.rs b/src/libstd/sys/redox/syscall/flag.rs index 0f61b9fa77b..0f1a2c23159 100644 --- a/src/libstd/sys/redox/syscall/flag.rs +++ b/src/libstd/sys/redox/syscall/flag.rs @@ -113,4 +113,46 @@ pub const SA_RESTART: usize = 0x10000000; pub const SA_NODEFER: usize = 0x40000000; pub const SA_RESETHAND: usize = 0x80000000; -pub const WNOHANG: usize = 1; +pub const WNOHANG: usize = 0x01; +pub const WUNTRACED: usize = 0x02; +pub const WCONTINUED: usize = 0x08; + +/// True if status indicates the child is stopped. +pub fn wifstopped(status: usize) -> bool { + (status & 0xff) == 0x7f +} + +/// If wifstopped(status), the signal that stopped the child. +pub fn wstopsig(status: usize) -> usize { + (status >> 8) & 0xff +} + +/// True if status indicates the child continued after a stop. +pub fn wifcontinued(status: usize) -> bool { + status == 0xffff +} + +/// True if STATUS indicates termination by a signal. +pub fn wifsignaled(status: usize) -> bool { + ((status & 0x7f) + 1) as i8 >= 2 +} + +/// If wifsignaled(status), the terminating signal. +pub fn wtermsig(status: usize) -> usize { + status & 0x7f +} + +/// True if status indicates normal termination. +pub fn wifexited(status: usize) -> bool { + wtermsig(status) == 0 +} + +/// If wifexited(status), the exit status. +pub fn wexitstatus(status: usize) -> usize { + (status >> 8) & 0xff +} + +/// True if status indicates a core dump was created. +pub fn wcoredump(status: usize) -> bool { + (status & 0x80) != 0 +} diff --git a/src/libstd/sys/redox/syscall/number.rs b/src/libstd/sys/redox/syscall/number.rs index 45cb40e3908..1e187565a67 100644 --- a/src/libstd/sys/redox/syscall/number.rs +++ b/src/libstd/sys/redox/syscall/number.rs @@ -36,6 +36,7 @@ pub const SYS_FCHMOD: usize = SYS_CLASS_FILE | 94; pub const SYS_FCHOWN: usize = SYS_CLASS_FILE | 207; pub const SYS_FCNTL: usize = SYS_CLASS_FILE | 55; pub const SYS_FEVENT: usize = SYS_CLASS_FILE | 927; +pub const SYS_FEXEC: usize = SYS_CLASS_FILE | 11; pub const SYS_FMAP: usize = SYS_CLASS_FILE | 90; pub const SYS_FUNMAP: usize = SYS_CLASS_FILE | 91; pub const SYS_FPATH: usize = SYS_CLASS_FILE | SYS_ARG_MSLICE | 928; @@ -50,7 +51,6 @@ pub const SYS_BRK: usize = 45; pub const SYS_CHDIR: usize = 12; pub const SYS_CLOCK_GETTIME: usize = 265; pub const SYS_CLONE: usize = 120; -pub const SYS_EXECVE: usize = 11; pub const SYS_EXIT: usize = 1; pub const SYS_FUTEX: usize = 240; pub const SYS_GETCWD: usize = 183; diff --git a/src/libstd/sys/unix/fd.rs b/src/libstd/sys/unix/fd.rs index af33d2636fb..5a81d6dfb67 100644 --- a/src/libstd/sys/unix/fd.rs +++ b/src/libstd/sys/unix/fd.rs @@ -46,7 +46,7 @@ impl FileDesc { pub fn raw(&self) -> c_int { self.fd } - /// Extracts the actual filedescriptor without closing it. + /// Extracts the actual file descriptor without closing it. pub fn into_raw(self) -> c_int { let fd = self.fd; mem::forget(self); diff --git a/src/libstd/sys/unix/rwlock.rs b/src/libstd/sys/unix/rwlock.rs index c754d5b8359..fcd6f7a27b6 100644 --- a/src/libstd/sys/unix/rwlock.rs +++ b/src/libstd/sys/unix/rwlock.rs @@ -14,7 +14,7 @@ use sync::atomic::{AtomicUsize, Ordering}; pub struct RWLock { inner: UnsafeCell<libc::pthread_rwlock_t>, - write_locked: UnsafeCell<bool>, + write_locked: UnsafeCell<bool>, // guarded by the `inner` RwLock num_readers: AtomicUsize, } @@ -52,13 +52,13 @@ impl RWLock { // allow that because it could lead to aliasing issues. if r == libc::EAGAIN { panic!("rwlock maximum reader count exceeded"); - } else if r == libc::EDEADLK || *self.write_locked.get() { + } else if r == libc::EDEADLK || (r == 0 && *self.write_locked.get()) { if r == 0 { self.raw_unlock(); } panic!("rwlock read lock would result in deadlock"); } else { - debug_assert_eq!(r, 0); + assert_eq!(r, 0); self.num_readers.fetch_add(1, Ordering::Relaxed); } } diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index a57b8dc7237..8a845efd413 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -233,7 +233,7 @@ pub use self::local::{LocalKey, AccessError}; /// /// You may want to use [`spawn`] instead of [`thread::spawn`], when you want /// to recover from a failure to launch a thread, indeed the free function will -/// panick where the `Builder` method will return a [`io::Result`]. +/// panic where the `Builder` method will return a [`io::Result`]. /// /// # Examples /// |
