Repository navigation
Synchronize native transport fork teardown - #6127
Conversation
Fork hooks, sends, and transport teardown share the exporter and its runtime. Serialize `close` and finalization against active fork lifecycles and in-flight sends so hooks cannot disappear mid-fork or the exporter be released during a send. Use a blocking mock agent to exercise these races deterministically instead of relying on timing delays.
A failed fork or `:before` callback can leave earlier callbacks holding resources. Always run the matching `:parent` callbacks, and continue running cleanup callbacks after one fails before re-raising the first error. Defer finalizer hook removal when it interrupts an active fork so the runtime and lifecycle locks are restored first.
Capture one callback snapshot for the complete fork lifecycle and register callback triplets atomically. This prevents concurrent registration or removal from pairing a `:before` callback with the wrong `:parent` or `:child` cleanup. Track lock acquisition explicitly so a reentrant `close` cannot release locks owned by the surrounding fork lifecycle.
|
Thank you for updating Change log entry section 👏 Visited at: 2026-07-30 12:12:00 UTC |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0ad246116c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
🎉 All green!🧪 All tests passed 🎯 Code Coverage (details) 🔗 Commit SHA: 3233f52 | Docs | Datadog PR Page | Give us feedback! |
BenchmarksBenchmark execution time: 2026-08-05 16:25:49 Comparing candidate commit df7082d in PR branch Found 0 performance improvements and 0 performance regressions! Performance is the same for 48 metrics, 1 unstable metrics.
|
0ad2461 to
b0c5772
Compare
Rely on per-fork callback snapshots to keep completion hooks alive after transport teardown. This removes the unsynchronised counter and finalizer polling that could leave waiting indefinitely while preserving runtime restoration for active forks.
Run all parent cleanup callbacks after a failed fork, but keep the original exception as the caller-visible failure. Log a secondary cleanup error instead of allowing it to replace the error that triggered cleanup.
Define the registry snapshot and mutex purpose where they are introduced, record the signal-trap limitation, and distinguish copied callback sets from closures that keep exporter state alive.
Strech
left a comment
There was a problem hiding this comment.
It's a bit hard to read and follow tests, but I would give non-blocking 👍🏼
Publish callback registry updates with immutable copy-on-write values so fork dispatch never acquires a Ruby mutex. This preserves one registry view for each lifecycle and allows ordinary fork dispatch from signal traps.
Associate atomically registered callback triplets within each immutable registry snapshot. If a before callback fails, run grouped parent cleanup only for triplets whose setup started while preserving standalone semantics.
Keep the signature synchronized with the immutable callback registry added for lock-free fork snapshots.
Make every callback dispatch identify the immutable registry view for its fork lifecycle. This prevents separate stages from accidentally observing different callback sets and removes a test-only compatibility default.
Expand the raising callback into a multiline block so it satisfies the repository Style/Semicolon rule.
AI-generated code disclosure: this PR was implemented with substantial AI assistance and manually reviewed and validated.
What does this PR do?
Makes native transport fork lifecycle dispatch atomic and failure-safe. It coordinates
closewith in-flight sends and forks, runs every completion callback before re-raising the first error, and prevents finalizer and reentrant-lock deadlocks.Motivation:
Native transport teardown can race with sends or fork handling, and exceptional callbacks can otherwise leave lifecycle work incomplete. This is the internal safety work tracked by APMSP-3823.
Change log entry
No.
Additional Notes:
How to test the change?