diff options
Diffstat (limited to 'library/std/src')
| -rw-r--r-- | library/std/src/os/unix/net/addr.rs | 10 | ||||
| -rw-r--r-- | library/std/src/sys/pal/unix/thread.rs | 6 | ||||
| -rw-r--r-- | library/std/src/sys/sync/rwlock/queue.rs | 2 | ||||
| -rw-r--r-- | library/std/src/thread/local.rs | 60 | ||||
| -rw-r--r-- | library/std/src/thread/mod.rs | 33 |
5 files changed, 66 insertions, 45 deletions
diff --git a/library/std/src/os/unix/net/addr.rs b/library/std/src/os/unix/net/addr.rs index 9757653e02c..1787eba0ef8 100644 --- a/library/std/src/os/unix/net/addr.rs +++ b/library/std/src/os/unix/net/addr.rs @@ -107,6 +107,16 @@ impl SocketAddr { addr: libc::sockaddr_un, mut len: libc::socklen_t, ) -> io::Result<SocketAddr> { + if cfg!(target_os = "openbsd") { + // on OpenBSD, getsockname(2) returns the actual size of the socket address, + // and not the len of the content. Figure out the length for ourselves. + // https://marc.info/?l=openbsd-bugs&m=170105481926736&w=2 + let sun_path: &[u8] = + unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&addr.sun_path) }; + len = core::slice::memchr::memchr(0, sun_path) + .map_or(len, |new_len| (new_len + sun_path_offset(&addr)) as libc::socklen_t); + } + if len == 0 { // When there is a datagram from unnamed unix socket // linux returns zero bytes of address diff --git a/library/std/src/sys/pal/unix/thread.rs b/library/std/src/sys/pal/unix/thread.rs index 5eb71f1f5ce..6a6bfc77a85 100644 --- a/library/std/src/sys/pal/unix/thread.rs +++ b/library/std/src/sys/pal/unix/thread.rs @@ -709,7 +709,7 @@ mod cgroups { // is created in an application with big thread-local storage requirements. // See #6233 for rationale and details. #[cfg(all(target_os = "linux", target_env = "gnu"))] -fn min_stack_size(attr: *const libc::pthread_attr_t) -> usize { +unsafe fn min_stack_size(attr: *const libc::pthread_attr_t) -> usize { // We use dlsym to avoid an ELF version dependency on GLIBC_PRIVATE. (#23628) // We shouldn't really be using such an internal symbol, but there's currently // no other way to account for the TLS size. @@ -723,11 +723,11 @@ fn min_stack_size(attr: *const libc::pthread_attr_t) -> usize { // No point in looking up __pthread_get_minstack() on non-glibc platforms. #[cfg(all(not(all(target_os = "linux", target_env = "gnu")), not(target_os = "netbsd")))] -fn min_stack_size(_: *const libc::pthread_attr_t) -> usize { +unsafe fn min_stack_size(_: *const libc::pthread_attr_t) -> usize { libc::PTHREAD_STACK_MIN } #[cfg(target_os = "netbsd")] -fn min_stack_size(_: *const libc::pthread_attr_t) -> usize { +unsafe fn min_stack_size(_: *const libc::pthread_attr_t) -> usize { 2048 // just a guess } diff --git a/library/std/src/sys/sync/rwlock/queue.rs b/library/std/src/sys/sync/rwlock/queue.rs index d1918855797..337cc6c2ca0 100644 --- a/library/std/src/sys/sync/rwlock/queue.rs +++ b/library/std/src/sys/sync/rwlock/queue.rs @@ -202,7 +202,7 @@ impl Node { fn prepare(&mut self) { // Fall back to creating an unnamed `Thread` handle to allow locking in // TLS destructors. - self.thread.get_or_init(|| thread::try_current().unwrap_or_else(|| Thread::new(None))); + self.thread.get_or_init(|| thread::try_current().unwrap_or_else(Thread::new_unnamed)); self.completed = AtomicBool::new(false); } diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs index fbb882e640b..c1b4440e560 100644 --- a/library/std/src/thread/local.rs +++ b/library/std/src/thread/local.rs @@ -53,25 +53,25 @@ use crate::fmt; /// # Examples /// /// ``` -/// use std::cell::RefCell; +/// use std::cell::Cell; /// use std::thread; /// -/// thread_local!(static FOO: RefCell<u32> = RefCell::new(1)); +/// thread_local!(static FOO: Cell<u32> = Cell::new(1)); /// -/// FOO.with_borrow(|v| assert_eq!(*v, 1)); -/// FOO.with_borrow_mut(|v| *v = 2); +/// assert_eq!(FOO.get(), 1); +/// FOO.set(2); /// /// // each thread starts out with the initial value of 1 /// let t = thread::spawn(move|| { -/// FOO.with_borrow(|v| assert_eq!(*v, 1)); -/// FOO.with_borrow_mut(|v| *v = 3); +/// assert_eq!(FOO.get(), 1); +/// FOO.set(3); /// }); /// /// // wait for the thread to complete and bail out on panic /// t.join().unwrap(); /// /// // we retain our original value of 2 despite the child thread -/// FOO.with_borrow(|v| assert_eq!(*v, 2)); +/// assert_eq!(FOO.get(), 2); /// ``` /// /// # Platform-specific behavior @@ -141,15 +141,16 @@ impl<T: 'static> fmt::Debug for LocalKey<T> { /// Publicity and attributes for each static are allowed. Example: /// /// ``` -/// use std::cell::RefCell; +/// use std::cell::{Cell, RefCell}; +/// /// thread_local! { -/// pub static FOO: RefCell<u32> = RefCell::new(1); +/// pub static FOO: Cell<u32> = Cell::new(1); /// -/// static BAR: RefCell<f32> = RefCell::new(1.0); +/// static BAR: RefCell<Vec<f32>> = RefCell::new(vec![1.0, 2.0]); /// } /// -/// FOO.with_borrow(|v| assert_eq!(*v, 1)); -/// BAR.with_borrow(|v| assert_eq!(*v, 1.0)); +/// assert_eq!(FOO.get(), 1); +/// BAR.with_borrow(|v| assert_eq!(v[1], 2.0)); /// ``` /// /// Note that only shared references (`&T`) to the inner data may be obtained, so a @@ -164,12 +165,13 @@ impl<T: 'static> fmt::Debug for LocalKey<T> { /// track any additional state. /// /// ``` -/// use std::cell::Cell; +/// use std::cell::RefCell; +/// /// thread_local! { -/// pub static FOO: Cell<u32> = const { Cell::new(1) }; +/// pub static FOO: RefCell<Vec<u32>> = const { RefCell::new(Vec::new()) }; /// } /// -/// assert_eq!(FOO.get(), 1); +/// FOO.with_borrow(|v| assert_eq!(v.len(), 0)); /// ``` /// /// See [`LocalKey` documentation][`std::thread::LocalKey`] for more @@ -279,10 +281,9 @@ impl<T: 'static> LocalKey<T> { where F: FnOnce(&T) -> R, { - unsafe { - let thread_local = (self.inner)(None).ok_or(AccessError)?; - Ok(f(thread_local)) - } + // SAFETY: `inner` is safe to call within the lifetime of the thread + let thread_local = unsafe { (self.inner)(None).ok_or(AccessError)? }; + Ok(f(thread_local)) } /// Acquires a reference to the value in this TLS key, initializing it with @@ -301,14 +302,17 @@ impl<T: 'static> LocalKey<T> { where F: FnOnce(Option<T>, &T) -> R, { - unsafe { - let mut init = Some(init); - let reference = (self.inner)(Some(&mut init)).expect( + let mut init = Some(init); + + // SAFETY: `inner` is safe to call within the lifetime of the thread + let reference = unsafe { + (self.inner)(Some(&mut init)).expect( "cannot access a Thread Local Storage value \ during or after destruction", - ); - f(init, reference) - } + ) + }; + + f(init, reference) } } @@ -377,7 +381,7 @@ impl<T: 'static> LocalKey<Cell<T>> { where T: Copy, { - self.with(|cell| cell.get()) + self.with(Cell::get) } /// Takes the contained value, leaving `Default::default()` in its place. @@ -407,7 +411,7 @@ impl<T: 'static> LocalKey<Cell<T>> { where T: Default, { - self.with(|cell| cell.take()) + self.with(Cell::take) } /// Replaces the contained value, returning the old value. @@ -578,7 +582,7 @@ impl<T: 'static> LocalKey<RefCell<T>> { where T: Default, { - self.with(|cell| cell.take()) + self.with(RefCell::take) } /// Replaces the contained value, returning the old value. diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index fd89edd4ace..604eb05040b 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -487,9 +487,11 @@ impl Builder { amt }); - let my_thread = Thread::new(name.map(|name| { - CString::new(name).expect("thread name may not contain interior null bytes") - })); + let my_thread = name.map_or_else(Thread::new_unnamed, |name| unsafe { + Thread::new( + CString::new(name).expect("thread name may not contain interior null bytes"), + ) + }); let their_thread = my_thread.clone(); let my_packet: Arc<Packet<'scope, T>> = Arc::new(Packet { @@ -711,7 +713,7 @@ pub(crate) fn set_current(thread: Thread) { /// In contrast to the public `current` function, this will not panic if called /// from inside a TLS destructor. pub(crate) fn try_current() -> Option<Thread> { - CURRENT.try_with(|current| current.get_or_init(|| Thread::new(None)).clone()).ok() + CURRENT.try_with(|current| current.get_or_init(|| Thread::new_unnamed()).clone()).ok() } /// Gets a handle to the thread that invokes it. @@ -1307,21 +1309,26 @@ pub struct Thread { } impl Thread { - // Used only internally to construct a thread object without spawning - pub(crate) fn new(name: Option<CString>) -> Thread { - if let Some(name) = name { - Self::new_inner(ThreadName::Other(name)) - } else { - Self::new_inner(ThreadName::Unnamed) - } + /// Used only internally to construct a thread object without spawning. + /// + /// # Safety + /// `name` must be valid UTF-8. + pub(crate) unsafe fn new(name: CString) -> Thread { + unsafe { Self::new_inner(ThreadName::Other(name)) } + } + + pub(crate) fn new_unnamed() -> Thread { + unsafe { Self::new_inner(ThreadName::Unnamed) } } // Used in runtime to construct main thread pub(crate) fn new_main() -> Thread { - Self::new_inner(ThreadName::Main) + unsafe { Self::new_inner(ThreadName::Main) } } - fn new_inner(name: ThreadName) -> Thread { + /// # Safety + /// If `name` is `ThreadName::Other(_)`, the contained string must be valid UTF-8. + unsafe fn new_inner(name: ThreadName) -> Thread { // We have to use `unsafe` here to construct the `Parker` in-place, // which is required for the UNIX implementation. // |
