Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions profiling/src/profiling/thread_utils.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::SAPI;
use libc::sched_yield;
use std::cell::OnceCell;
use std::mem::MaybeUninit;
use std::thread::JoinHandle;
Expand Down Expand Up @@ -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
Expand All @@ -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() {
Expand Down
Loading