Skip to content

Commit 7340e29

Browse files
committed
fix(profiling): reset sampler scratch vectors after fork
1 parent ce98e98 commit 7340e29

1 file changed

Lines changed: 7 additions & 0 deletions

File tree

  • ddtrace/internal/datadog/profiling/stack/src

ddtrace/internal/datadog/profiling/stack/src/sampler.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,8 @@ Sampler::capture_samples(const microsecond_t wall_time_us)
262262
const bool interpreter_snapshot_complete =
263263
for_each_interp(runtime, [&](InterpreterInfo& interp) { interpreter_candidates.push_back(interp); });
264264
#if PY_VERSION_HEX >= 0x030e0000
265+
// This lock-free snapshot can race with code destruction during the sampling cycle. In that case, the current
266+
// cycle may use stale frame metadata; the next cycle observes the generation change and clears the cache.
265267
if (!echion->update_code_object_generations(interpreter_candidates, interpreter_snapshot_complete)) {
266268
return;
267269
}
@@ -604,6 +606,11 @@ Sampler::postfork_child()
604606
new (&pause_mutex_) std::mutex();
605607
new (&pause_cv_) std::condition_variable();
606608

609+
// The parent sampling thread may have been mutating these vectors when fork took its snapshot. Abandon their
610+
// inherited storage instead of traversing potentially inconsistent state in clear() or push_back().
611+
new (&interpreter_candidates) std::vector<InterpreterInfo>();
612+
new (&thread_candidates) std::vector<PyThreadState>();
613+
607614
// Clear stale echion state (mutexes, maps) from parent process
608615
if (echion) {
609616
echion->postfork_child();

0 commit comments

Comments
 (0)