diff --git a/profiling/src/profiling/thread_utils.rs b/profiling/src/profiling/thread_utils.rs index 52fabe629d..d52c62cec3 100644 --- a/profiling/src/profiling/thread_utils.rs +++ b/profiling/src/profiling/thread_utils.rs @@ -1,5 +1,4 @@ use crate::SAPI; -use libc::sched_yield; use std::cell::OnceCell; use std::mem::MaybeUninit; use std::thread::JoinHandle; @@ -59,6 +58,8 @@ pub struct TimeoutError { timeout_ms: u128, } +const JOIN_POLL_INTERVAL: Duration = Duration::from_millis(100); + /// Waits for the handle to be finished. If finished, it will join the handle. /// Otherwise, it will leak the handle and return an error. /// # Panics @@ -69,15 +70,18 @@ pub fn join_timeout(handle: JoinHandle<()>, timeout: Duration) -> Result<(), Tim // correct way to do this, but we've observed this can panic: // https://github.com/DataDog/dd-trace-php/issues/1919 // Thus far, we have not been able to reproduce it and address the root - // cause. So, for now, mitigate it instead with a busy loop. + // cause. So, for now, mitigate it instead with a loop. let start = Instant::now(); while !handle.is_finished() { - unsafe { sched_yield() }; - if start.elapsed() >= timeout { + let elapsed = start.elapsed(); + if elapsed >= timeout { let thread = handle.thread().name().unwrap_or("{unknown}").to_string(); let timeout_ms = timeout.as_millis(); return Err(TimeoutError { thread, timeout_ms }); } + + let remaining = timeout.saturating_sub(elapsed); + std::thread::sleep(std::cmp::min(JOIN_POLL_INTERVAL, remaining)); } if let Err(err) = handle.join() {