summaryrefslogtreecommitdiffstats
path: root/library/std/src/sys/common
diff options
context:
space:
mode:
Diffstat (limited to 'library/std/src/sys/common')
-rw-r--r--library/std/src/sys/common/small_c_string.rs2
-rw-r--r--library/std/src/sys/common/tests.rs4
-rw-r--r--library/std/src/sys/common/thread_local/fast_local.rs22
-rw-r--r--library/std/src/sys/common/thread_local/mod.rs21
4 files changed, 35 insertions, 14 deletions
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<T, F>(path: &Path, f: F) -> io::Result<T>
where
F: FnOnce(&CStr) -> io::Result<T>,
{
- 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::<String>();
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<T> fmt::Debug for Key<T> {
f.debug_struct("Key").finish_non_exhaustive()
}
}
-
impl<T> Key<T> {
pub const fn new() -> Key<T> {
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");
+ }
+ }
+}