From dc0db358abe19481e475e10c32149b53370f1a1c Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 30 May 2024 05:57:31 +0200 Subject: Merging upstream version 1.72.1+dfsg1. Signed-off-by: Daniel Baumann --- library/std/src/sys/common/small_c_string.rs | 2 +- library/std/src/sys/common/tests.rs | 4 ++-- .../std/src/sys/common/thread_local/fast_local.rs | 22 +++++++++++----------- library/std/src/sys/common/thread_local/mod.rs | 21 +++++++++++++++++++++ 4 files changed, 35 insertions(+), 14 deletions(-) (limited to 'library/std/src/sys/common') diff --git a/library/std/src/sys/common/small_c_string.rs b/library/std/src/sys/common/small_c_string.rs index 01acd5191..963d17a47 100644 --- a/library/std/src/sys/common/small_c_string.rs +++ b/library/std/src/sys/common/small_c_string.rs @@ -19,7 +19,7 @@ pub fn run_path_with_cstr(path: &Path, f: F) -> io::Result where F: FnOnce(&CStr) -> io::Result, { - run_with_cstr(path.as_os_str().bytes(), f) + run_with_cstr(path.as_os_str().as_os_str_bytes(), f) } #[inline] diff --git a/library/std/src/sys/common/tests.rs b/library/std/src/sys/common/tests.rs index fb6f5d6af..0a1cbcbe8 100644 --- a/library/std/src/sys/common/tests.rs +++ b/library/std/src/sys/common/tests.rs @@ -8,7 +8,7 @@ use core::iter::repeat; fn stack_allocation_works() { let path = Path::new("abc"); let result = run_path_with_cstr(path, |p| { - assert_eq!(p, &*CString::new(path.as_os_str().bytes()).unwrap()); + assert_eq!(p, &*CString::new(path.as_os_str().as_os_str_bytes()).unwrap()); Ok(42) }); assert_eq!(result.unwrap(), 42); @@ -25,7 +25,7 @@ fn heap_allocation_works() { let path = repeat("a").take(384).collect::(); let path = Path::new(&path); let result = run_path_with_cstr(path, |p| { - assert_eq!(p, &*CString::new(path.as_os_str().bytes()).unwrap()); + assert_eq!(p, &*CString::new(path.as_os_str().as_os_str_bytes()).unwrap()); Ok(42) }); assert_eq!(result.unwrap(), 42); diff --git a/library/std/src/sys/common/thread_local/fast_local.rs b/library/std/src/sys/common/thread_local/fast_local.rs index 447044a79..bc5da1a18 100644 --- a/library/std/src/sys/common/thread_local/fast_local.rs +++ b/library/std/src/sys/common/thread_local/fast_local.rs @@ -33,20 +33,21 @@ pub macro thread_local_inner { // 1 == dtor registered, dtor not run // 2 == dtor registered and is running or has run #[thread_local] - static mut STATE: $crate::primitive::u8 = 0; + static STATE: $crate::cell::Cell<$crate::primitive::u8> = $crate::cell::Cell::new(0); + // Safety: Performs `drop_in_place(ptr as *mut $t)`, and requires + // all that comes with it. unsafe extern "C" fn destroy(ptr: *mut $crate::primitive::u8) { - let ptr = ptr as *mut $t; - - unsafe { - $crate::debug_assert_eq!(STATE, 1); - STATE = 2; - $crate::ptr::drop_in_place(ptr); - } + $crate::thread::local_impl::abort_on_dtor_unwind(|| { + let old_state = STATE.replace(2); + $crate::debug_assert_eq!(old_state, 1); + // Safety: safety requirement is passed on to caller. + unsafe { $crate::ptr::drop_in_place(ptr.cast::<$t>()); } + }); } unsafe { - match STATE { + match STATE.get() { // 0 == we haven't registered a destructor, so do // so now. 0 => { @@ -54,7 +55,7 @@ pub macro thread_local_inner { $crate::ptr::addr_of_mut!(VAL) as *mut $crate::primitive::u8, destroy, ); - STATE = 1; + STATE.set(1); $crate::option::Option::Some(&VAL) } // 1 == the destructor is registered and the value @@ -148,7 +149,6 @@ impl fmt::Debug for Key { f.debug_struct("Key").finish_non_exhaustive() } } - impl Key { pub const fn new() -> Key { Key { inner: LazyKeyInner::new(), dtor_state: Cell::new(DtorState::Unregistered) } diff --git a/library/std/src/sys/common/thread_local/mod.rs b/library/std/src/sys/common/thread_local/mod.rs index 77f645883..975509bd4 100644 --- a/library/std/src/sys/common/thread_local/mod.rs +++ b/library/std/src/sys/common/thread_local/mod.rs @@ -101,3 +101,24 @@ mod lazy { } } } + +/// Run a callback in a scenario which must not unwind (such as a `extern "C" +/// fn` declared in a user crate). If the callback unwinds anyway, then +/// `rtabort` with a message about thread local panicking on drop. +#[inline] +pub fn abort_on_dtor_unwind(f: impl FnOnce()) { + // Using a guard like this is lower cost. + let guard = DtorUnwindGuard; + f(); + core::mem::forget(guard); + + struct DtorUnwindGuard; + impl Drop for DtorUnwindGuard { + #[inline] + fn drop(&mut self) { + // This is not terribly descriptive, but it doesn't need to be as we'll + // already have printed a panic message at this point. + rtabort!("thread local panicked on drop"); + } + } +} -- cgit v1.2.3