Skip to content

Commit

Permalink
feat: improve panics on thread ID bit exhaustion
Browse files Browse the repository at this point in the history
Signed-off-by: Eliza Weisman <[email protected]>
  • Loading branch information
hawkw committed Aug 1, 2021
1 parent f816d62 commit 9ecb8e6
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 8 deletions.
19 changes: 19 additions & 0 deletions src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,22 @@ macro_rules! test_dbg {
}
};
}

macro_rules! panic_in_drop {
($($arg:tt)*) => {
if !std::thread::panicking() {
panic!($($arg)*)
} else {
let thread = std::thread::current();
eprintln!(
"thread '{thread}' attempted to panic at '{msg}', {file}:{line}:{col}\n\
note: we were already unwinding due to a previous panic.",
thread = thread.name().unwrap_or("<unnamed>"),
msg = format_args!($($arg)*),
file = file!(),
line = line!(),
col = column!(),
);
}
}
}
29 changes: 21 additions & 8 deletions src/tid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use std::{
collections::VecDeque,
fmt,
marker::PhantomData,
sync::PoisonError,
};

/// Uniquely identifies a thread.
Expand Down Expand Up @@ -138,10 +139,10 @@ impl Registration {
#[inline(always)]
fn current<C: cfg::Config>(&self) -> Tid<C> {
if let Some(tid) = self.0.get().map(Tid::new) {
tid
} else {
self.register()
return tid;
}

self.register()
}

#[cold]
Expand All @@ -157,8 +158,21 @@ impl Registration {
None
}
})
.unwrap_or_else(|| REGISTRY.next.fetch_add(1, Ordering::AcqRel));
debug_assert!(id <= Tid::<C>::BITS, "thread ID overflow!");
.unwrap_or_else(|| {
let id = REGISTRY.next.fetch_add(1, Ordering::AcqRel);
if id > Tid::<C>::BITS {
panic_in_drop!(
"creating a new thread ID ({}) would exceed the \
maximum number of thread ID bits specified in {} \
({})",
id,
std::any::type_name::<C>(),
Tid::<C>::BITS,
);
}
id
});

self.0.set(Some(id));
Tid::new(id)
}
Expand All @@ -173,9 +187,8 @@ impl Registration {
impl Drop for Registration {
fn drop(&mut self) {
if let Some(id) = self.0.get() {
if let Ok(mut free) = REGISTRY.free.lock() {
free.push_back(id);
}
let mut free_list = REGISTRY.free.lock().unwrap_or_else(PoisonError::into_inner);
free_list.push_back(id);
}
}
}

0 comments on commit 9ecb8e6

Please sign in to comment.