Skip to content

Commit dc76d1f

Browse files
committed
Retry for 0 frames
1 parent 4f21b6e commit dc76d1f

1 file changed

Lines changed: 15 additions & 4 deletions

File tree

libdd-crashtracker/src/receiver/ptrace_collector.rs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,11 @@ fn is_transient_ptrace_error(err: &PtraceError) -> bool {
410410
///
411411
/// Uses a single per-thread deadline across attempts so that a slow thread
412412
/// cannot consume more than STOP_TIMEOUT_PER_THREAD total.
413+
///
414+
/// A capture that succeeds but produces zero frames is also retried: on a
415+
/// running thread with a confirmed non-zero IP, empty frames indicates a
416+
/// transient libunwind issue (e.g. stale address-space cache state) rather
417+
/// than a permanent problem.
413418
fn capture_with_retry(
414419
tid: libc::pid_t,
415420
resolve_frames: crate::StacktraceCollection,
@@ -418,10 +423,16 @@ fn capture_with_retry(
418423
) -> Option<CapturedThreadContext> {
419424
let thread_deadline = (Instant::now() + STOP_TIMEOUT_PER_THREAD).min(overall_deadline);
420425

421-
match capture_thread_context(tid, resolve_frames, addr_space, thread_deadline) {
422-
Ok(ctx) => return Some(ctx),
423-
Err(ref e) if is_transient_ptrace_error(e) => {}
424-
Err(_) => return None,
426+
let should_retry =
427+
match capture_thread_context(tid, resolve_frames, addr_space, thread_deadline) {
428+
Ok(ctx) if !ctx.stack_trace.frames.is_empty() => return Some(ctx),
429+
Ok(_) => true,
430+
Err(ref e) if is_transient_ptrace_error(e) => true,
431+
Err(_) => false,
432+
};
433+
434+
if !should_retry {
435+
return None;
425436
}
426437

427438
let remaining = thread_deadline.saturating_duration_since(Instant::now());

0 commit comments

Comments
 (0)