Skip to content

feat(profiling): report the foreign SIGSEGV/SIGBUS owner to logs and telemetry - #20589

Draft
vlad-scherbich wants to merge 1 commit into
vlad/segv-diag-owner-namingfrom
vlad/segv-diag-telemetry
Draft

vlad-scherbich wants to merge 1 commit into
vlad/segv-diag-owner-namingfrom
vlad/segv-diag-telemetry

Conversation

@vlad-scherbich

Copy link
Copy Markdown
Contributor

Stacked on #20588. Review that one first; the diff below is only the delta.

What gap this addresses

The owner string #20588 builds only reaches stderr, which nobody running in a container
sees. A takeover pins the process to the slower syscall memory copy for its whole life,
or stops stack sampling outright, and neither outcome is visible anywhere we can query.

Evidence it is real

We concluded the sticky cycle guard in danger.cc is near-unreachable because re-entry
needs a subsequent SIGBUS and we had seen zero — but nobody could confirm that,
because nothing reports which signal was lost. The lost_signals tag is what settles
it, and it decides whether the SIGBUS-only handler paths are worth keeping.

What it does

The sampling thread latches the notice on Sampler instead of logging in place (it
cannot touch Python). StackCollector.snapshot() drains it once per process and emits
a LOG.warning — LOG.error when sampling stopped — plus a telemetry log tagged with
the normalized owner, whether the handler was already foreign at end of warmup, and
lost_signals (sigsegv, sigbus, or sigsegv_sigbus). Owner strings are normalized
to a bounded set so the tag cannot carry an unbounded address, and the value is kept
comma-free because add_log joins tags on commas.

What it does NOT do

  • No new telemetry mechanism; uses the existing telemetry_writer.add_log.
  • Fires once per process, not per sample.
  • Does not attempt to reclaim the handler.

…telemetry

The owner string the sampler builds only reached stderr, which a customer running
in a container usually never sees. A takeover pins the process to the slower
syscall-based memory copy for the rest of its life, or stops stack sampling
outright when no safe fallback exists, and neither outcome was visible anywhere
the profiling team can query.

Latch the notice on the sampler, drain it once per process from
StackCollector.snapshot(), and emit it as a LOG.warning (LOG.error when sampling
stopped) plus a telemetry log. The sampling thread cannot touch Python, hence the
latch and the take-once drain rather than logging in place.

The telemetry tags carry the normalized owner, whether the handler was already
foreign when warmup ended, and lost_signals - sigsegv, sigbus or sigsegv_sigbus.
Separating the two signals is the point of that last tag: whether SIGBUS ever
changes hands in the field decides whether the handler paths only a SIGBUS can
reach are worth keeping, and nothing measures that today.
@cit-pr-commenter-54b7da

Copy link
Copy Markdown

Codeowners resolved as

Resolved from the full PR diff against vlad/segv-diag-owner-naming using the target branch CODEOWNERS file.
CODEOWNERS team requests not listed below are not required by the current file set.

ddtrace/internal/datadog/profiling/stack/__init__.pyi                   @DataDog/profiling-python
ddtrace/internal/datadog/profiling/stack/_stack.pyi                     @DataDog/profiling-python
ddtrace/internal/datadog/profiling/stack/include/sampler.hpp            @DataDog/profiling-python
ddtrace/internal/datadog/profiling/stack/src/sampler.cpp                @DataDog/profiling-python
ddtrace/internal/datadog/profiling/stack/src/stack.cpp                  @DataDog/profiling-python
ddtrace/profiling/collector/stack.py                                    @DataDog/profiling-python
releasenotes/notes/prof-report-foreign-segv-handler-telemetry-8f3a6c1e04b95d27.yaml  @DataDog/apm-python
tests/profiling/collector/test_collector.py                             @DataDog/profiling-python
tests/profiling/collector/test_copy_memory_stats.py                     @DataDog/profiling-python
tests/profiling/collector/test_stack_native.py                          @DataDog/profiling-python

@cit-pr-commenter-54b7da

Copy link
Copy Markdown

Dependency direction analysis

⚠️ Existing dependency direction violations

There are 201 dependency direction violations that already exist on the base branch and have not been changed by this PR.

Show existing violations (showing 5 of 201 highest severity)
ddtrace.internal.tracemethods -×-> ddtrace.trace  (internal-core -> product:tracing, score=132)
ddtrace.llmobs._integrations.mcp -×-> ddtrace.trace  (product:llmobs -> product:tracing, score=130)
ddtrace.llmobs._integrations.langchain -×-> ddtrace.trace  (product:llmobs -> product:tracing, score=130)
ddtrace.internal.opentelemetry.trace -×-> ddtrace.trace  (product:opentelemetry -> product:tracing, score=130)
ddtrace.appsec._listeners -×-> ddtrace.trace  (product:appsec -> product:tracing, score=130)

To see all violations, download the layers-base.json and layers-pr.json artifacts from this CI job and run:

uv run --script scripts/import-analysis/layers.py compare layers-base.json layers-pr.json

@cit-pr-commenter-54b7da

Copy link
Copy Markdown

Circular import analysis

⚠️ Existing circular imports

There are 1 circular imports that already exist on the base branch and have not been changed by this PR.

ddtrace.errortracking._handled_exceptions.bytecode_injector -> ddtrace.errortracking._handled_exceptions.callbacks -> ddtrace.errortracking._handled_exceptions.collector -> ddtrace.errortracking._handled_exceptions.bytecode_reporting -> ddtrace.errortracking._handled_exceptions.bytecode_injector

@datadog-prod-us1-5

datadog-prod-us1-5 Bot commented Sep 27, 2026 •

Copy link
Copy Markdown
Contributor

Tests

🎉 All green!

🧪 All tests passed
❄️ No new flaky tests detected

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: 6e1ea90 | Docs | View more details | Give us feedback!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant