Use pthread_t instead of numeric thread id

This commit is contained in:
Zachary S
2024-07-03 13:28:44 -05:00
parent 5e83fafd88
commit 897fb6cb1a

View File

@@ -26,60 +26,27 @@ cfg_if::cfg_if! {
/// * If it is called again on a different thread, it will wait in a loop /// * If it is called again on a different thread, it will wait in a loop
/// (waiting for the process to exit). /// (waiting for the process to exit).
pub(crate) fn unique_thread_exit() { pub(crate) fn unique_thread_exit() {
let this_thread_id = unsafe { libc::gettid() }; let this_thread_id = unsafe { libc::pthread_self() };
debug_assert_ne!(this_thread_id, 0, "thread ID cannot be zero"); use crate::sync::{Mutex, PoisonError};
#[cfg(target_has_atomic = "32")] static EXITING_THREAD_ID: Mutex<Option<libc::pthread_t>> = Mutex::new(None);
{ let mut exiting_thread_id =
use crate::sync::atomic::{AtomicI32, Ordering}; EXITING_THREAD_ID.lock().unwrap_or_else(PoisonError::into_inner);
static EXITING_THREAD_ID: AtomicI32 = AtomicI32::new(0); match *exiting_thread_id {
match EXITING_THREAD_ID.compare_exchange( None => {
0,
this_thread_id,
Ordering::Relaxed,
Ordering::Relaxed,
) {
Ok(_zero) => {
// This is the first thread to call `unique_thread_exit`,
// and this is the first time it is called.
// Set EXITING_THREAD_ID to this thread's ID (done by the
// compare_exchange) and return.
}
Err(id) if id == this_thread_id => {
// This is the first thread to call `unique_thread_exit`,
// but this is the second time it is called.
// Abort the process.
core::panicking::panic_nounwind("std::process::exit called re-entrantly")
}
Err(_) => {
// This is not the first thread to call `unique_thread_exit`.
// Pause until the process exits.
loop {
// Safety: libc::pause is safe to call.
unsafe { libc::pause(); }
}
}
}
}
#[cfg(not(target_has_atomic = "32"))]
{
use crate::sync::{Mutex, PoisonError};
static EXITING_THREAD_ID: Mutex<i32> = Mutex::new(0);
let mut exiting_thread_id =
EXITING_THREAD_ID.lock().unwrap_or_else(PoisonError::into_inner);
if *exiting_thread_id == 0 {
// This is the first thread to call `unique_thread_exit`, // This is the first thread to call `unique_thread_exit`,
// and this is the first time it is called. // and this is the first time it is called.
// Set EXITING_THREAD_ID to this thread's ID and return. // Set EXITING_THREAD_ID to this thread's ID and return.
*exiting_thread_id = this_thread_id; *exiting_thread_id = Some(this_thread_id);
} else if *exiting_thread_id == this_thread_id { },
Some(exiting_thread_id) if exiting_thread_id == this_thread_id => {
// This is the first thread to call `unique_thread_exit`, // This is the first thread to call `unique_thread_exit`,
// but this is the second time it is called. // but this is the second time it is called.
// Abort the process. // Abort the process.
core::panicking::panic_nounwind("std::process::exit called re-entrantly") core::panicking::panic_nounwind("std::process::exit called re-entrantly")
} else { }
Some(_) => {
// This is not the first thread to call `unique_thread_exit`. // This is not the first thread to call `unique_thread_exit`.
// Pause until the process exits. // Pause until the process exits.
// Park until the process exits.
drop(exiting_thread_id); drop(exiting_thread_id);
loop { loop {
// Safety: libc::pause is safe to call. // Safety: libc::pause is safe to call.