Skip to content

feat(library-config): add macOS and Windows process context#2238

Open
cataphract wants to merge 3 commits into
glopes/otel-process-ctx-linux-updatefrom
glopes/otel-process-ctx-macos-windows
Open

feat(library-config): add macOS and Windows process context#2238
cataphract wants to merge 3 commits into
glopes/otel-process-ctx-linux-updatefrom
glopes/otel-process-ctx-macos-windows

Conversation

@cataphract

@cataphract cataphract commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

This is 3/3 in the stacked process-context series and depends on #2237.

It adds process-context publishing and same-process reading on macOS and Windows while reusing the shared protocol introduced by the preceding PRs:

  • macOS exports otel_process_ctx_v2 and discovers it with dlsym;
  • Windows exports the same symbol and discovers it with GetProcAddress;
  • adds platform-specific allocation, monotonic-clock, mapping-discovery, and safe memory-copy implementations;
  • updates tracer-metadata publication and the FFI layer to use process contexts on all supported desktop platforms;
  • adds reader-only CI coverage so the independently selectable feature configuration remains tested.

Why?

The OpenTelemetry process-context discovery convention based on /proc/self/maps is Linux-specific. macOS and Windows therefore need an explicit exported-symbol discovery mechanism and platform-native memory-copy primitives, while the publication format and reader validation can remain shared.

Keeping this as the top layer isolates the new platform support from the Linux reorganization in #2228 and the Linux behavior updates in #2237.

Impact

The platform-agnostic process-context API now works on Linux, macOS, and Windows. Linux behavior is unchanged by this layer. On macOS and Windows, tracer metadata can be published and read within the current process through the exported process-context symbol.

Validation

Validated at this commit with:

  • Linux all-feature and reader-only tests;
  • Windows all-feature, reader-only, and FFI storage tests under Wine;
  • targeted macOS tests;
  • workspace formatting, Clippy, default/all-feature tests, and documentation tests.

Stack

  1. refactor(library-config): reorganize Linux process context #2228 — reorganize the Linux process context
  2. fix(library-config): update Linux process context #2237 — update the Linux implementation
  3. feat(library-config): add macOS and Windows process context #2238 — add macOS and Windows support

@github-actions

github-actions Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

📚 Documentation Check Results

⚠️ 843 documentation warning(s) found

📦 libdd-library-config-ffi - 578 warning(s)

📦 libdd-library-config - 265 warning(s)


Updated: 2026-07-14 23:10:10 UTC | Commit: 8d43066 | missing-docs job results

@github-actions

github-actions Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

🔒 Cargo Deny Results

⚠️ 2 issue(s) found, showing only errors (advisories, bans, sources)

📦 libdd-library-config-ffi - 1 error(s)

Show output
error[unsound]: Rand is unsound with a custom logger using `rand::rng()`
    ┌─ /home/runner/work/libdatadog/libdatadog/Cargo.lock:119:1
    │
119 │ rand 0.8.5 registry+https://github.com/rust-lang/crates.io-index
    │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ unsound advisory detected
    │
    ├ ID: RUSTSEC-2026-0097
    ├ Advisory: https://rustsec.org/advisories/RUSTSEC-2026-0097
    ├ It has been reported (by @lopopolo) that the `rand` library is [unsound](https://rust-lang.github.io/unsafe-code-guidelines/glossary.html#soundness-of-code--of-a-library) (i.e. that safe code using the public API can cause Undefined Behaviour) when all the following conditions are met:
      
      - The `log` and `thread_rng` features are enabled
      - A [custom logger](https://docs.rs/log/latest/log/#implementing-a-logger) is defined
      - The custom logger accesses `rand::rng()` (previously `rand::thread_rng()`) and calls any `TryRng` (previously `RngCore`) methods on `ThreadRng`
      - The `ThreadRng` (attempts to) reseed while called from the custom logger (this happens every 64 kB of generated data)
      - Trace-level logging is enabled or warn-level logging is enabled and the random source (the `getrandom` crate) is unable to provide a new seed
      
      `TryRng` (previously `RngCore`) methods for `ThreadRng` use `unsafe` code to cast `*mut BlockRng<ReseedingCore>` to `&mut BlockRng<ReseedingCore>`. When all the above conditions are met this results in an aliased mutable reference, violating the Stacked Borrows rules. Miri is able to detect this violation in sample code. Since construction of [aliased mutable references is Undefined Behaviour](https://doc.rust-lang.org/stable/nomicon/references.html), the behaviour of optimized builds is hard to predict.
    ├ Announcement: https://github.com/rust-random/rand/pull/1763
    ├ Solution: Upgrade to >=0.10.1 OR <0.10.0, >=0.9.3 OR <0.9.0, >=0.8.6 (try `cargo update -p rand`)
    ├ rand v0.8.5
      ├── (dev) libdd-common v5.1.0
      │   ├── libdd-common-ffi v37.0.0
      │   │   └── libdd-library-config-ffi v0.0.2
      │   └── libdd-library-config-ffi v0.0.2 (*)
      └── libdd-library-config v3.0.0
          └── libdd-library-config-ffi v0.0.2 (*)

advisories FAILED, bans ok, sources ok

📦 libdd-library-config - 1 error(s)

Show output
error[unsound]: Rand is unsound with a custom logger using `rand::rng()`
   ┌─ /home/runner/work/libdatadog/libdatadog/Cargo.lock:47:1
   │
47 │ rand 0.8.5 registry+https://github.com/rust-lang/crates.io-index
   │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ unsound advisory detected
   │
   ├ ID: RUSTSEC-2026-0097
   ├ Advisory: https://rustsec.org/advisories/RUSTSEC-2026-0097
   ├ It has been reported (by @lopopolo) that the `rand` library is [unsound](https://rust-lang.github.io/unsafe-code-guidelines/glossary.html#soundness-of-code--of-a-library) (i.e. that safe code using the public API can cause Undefined Behaviour) when all the following conditions are met:
     
     - The `log` and `thread_rng` features are enabled
     - A [custom logger](https://docs.rs/log/latest/log/#implementing-a-logger) is defined
     - The custom logger accesses `rand::rng()` (previously `rand::thread_rng()`) and calls any `TryRng` (previously `RngCore`) methods on `ThreadRng`
     - The `ThreadRng` (attempts to) reseed while called from the custom logger (this happens every 64 kB of generated data)
     - Trace-level logging is enabled or warn-level logging is enabled and the random source (the `getrandom` crate) is unable to provide a new seed
     
     `TryRng` (previously `RngCore`) methods for `ThreadRng` use `unsafe` code to cast `*mut BlockRng<ReseedingCore>` to `&mut BlockRng<ReseedingCore>`. When all the above conditions are met this results in an aliased mutable reference, violating the Stacked Borrows rules. Miri is able to detect this violation in sample code. Since construction of [aliased mutable references is Undefined Behaviour](https://doc.rust-lang.org/stable/nomicon/references.html), the behaviour of optimized builds is hard to predict.
   ├ Announcement: https://github.com/rust-random/rand/pull/1763
   ├ Solution: Upgrade to >=0.10.1 OR <0.10.0, >=0.9.3 OR <0.9.0, >=0.8.6 (try `cargo update -p rand`)
   ├ rand v0.8.5
     └── libdd-library-config v3.0.0

advisories FAILED, bans ok, sources ok

Updated: 2026-07-14 23:11:37 UTC | Commit: 8d43066 | dependency-check job results

@pr-commenter

pr-commenter Bot commented Jul 14, 2026

Copy link
Copy Markdown

Benchmarks

Comparison

Benchmark execution time: 2026-07-14 23:41:01

Comparing candidate commit 954186b in PR branch glopes/otel-process-ctx-macos-windows with baseline commit 97138bc in branch glopes/otel-process-ctx-linux-update.

Found 0 performance improvements and 2 performance regressions! Performance is the same for 140 metrics, 0 unstable metrics.

Explanation

This is an A/B test comparing a candidate commit's performance against that of a baseline commit. Performance changes are noted in the tables below as:

  • 🟩 = significantly better candidate vs. baseline
  • 🟥 = significantly worse candidate vs. baseline

We compute a confidence interval (CI) over the relative difference of means between metrics from the candidate and baseline commits, considering the baseline as the reference.

If the CI is entirely outside the configured SIGNIFICANT_IMPACT_THRESHOLD (or the deprecated UNCONFIDENCE_THRESHOLD), the change is considered significant.

Feel free to reach out to #apm-benchmarking-platform on Slack if you have any questions.

More details about the CI and significant changes

You can imagine this CI as a range of values that is likely to contain the true difference of means between the candidate and baseline commits.

CIs of the difference of means are often centered around 0%, because often changes are not that big:

---------------------------------(------|---^--------)-------------------------------->
                              -0.6%    0%  0.3%     +1.2%
                                 |          |        |
         lower bound of the CI --'          |        |
sample mean (center of the CI) -------------'        |
         upper bound of the CI ----------------------'

As described above, a change is considered significant if the CI is entirely outside the configured SIGNIFICANT_IMPACT_THRESHOLD (or the deprecated UNCONFIDENCE_THRESHOLD).

For instance, for an execution time metric, this confidence interval indicates a significantly worse performance:

----------------------------------------|---------|---(---------^---------)---------->
                                       0%        1%  1.3%      2.2%      3.1%
                                                  |   |         |         |
       significant impact threshold --------------'   |         |         |
                      lower bound of CI --------------'         |         |
       sample mean (center of the CI) --------------------------'         |
                      upper bound of CI ----------------------------------'

scenario:profiles_dictionary/profile_string_inserts/threads/1

  • 🟥 execution_time [+12.815µs; +14.641µs] or [+4.196%; +4.794%]
  • 🟥 throughput [-154115.792op/s; -134450.242op/s] or [-4.596%; -4.010%]

Benchmark execution time: 2026-07-14 23:56:14

Comparing candidate commit 954186b in PR branch glopes/otel-process-ctx-macos-windows with baseline commit 97138bc in branch glopes/otel-process-ctx-linux-update.

Found 3 performance improvements and 3 performance regressions! Performance is the same for 171 metrics, 10 unstable metrics.

Explanation

This is an A/B test comparing a candidate commit's performance against that of a baseline commit. Performance changes are noted in the tables below as:

  • 🟩 = significantly better candidate vs. baseline
  • 🟥 = significantly worse candidate vs. baseline

We compute a confidence interval (CI) over the relative difference of means between metrics from the candidate and baseline commits, considering the baseline as the reference.

If the CI is entirely outside the configured SIGNIFICANT_IMPACT_THRESHOLD (or the deprecated UNCONFIDENCE_THRESHOLD), the change is considered significant.

Feel free to reach out to #apm-benchmarking-platform on Slack if you have any questions.

More details about the CI and significant changes

You can imagine this CI as a range of values that is likely to contain the true difference of means between the candidate and baseline commits.

CIs of the difference of means are often centered around 0%, because often changes are not that big:

---------------------------------(------|---^--------)-------------------------------->
                              -0.6%    0%  0.3%     +1.2%
                                 |          |        |
         lower bound of the CI --'          |        |
sample mean (center of the CI) -------------'        |
         upper bound of the CI ----------------------'

As described above, a change is considered significant if the CI is entirely outside the configured SIGNIFICANT_IMPACT_THRESHOLD (or the deprecated UNCONFIDENCE_THRESHOLD).

For instance, for an execution time metric, this confidence interval indicates a significantly worse performance:

----------------------------------------|---------|---(---------^---------)---------->
                                       0%        1%  1.3%      2.2%      3.1%
                                                  |   |         |         |
       significant impact threshold --------------'   |         |         |
                      lower bound of CI --------------'         |         |
       sample mean (center of the CI) --------------------------'         |
                      upper bound of CI ----------------------------------'

scenario:alloc_free/sampled_system_fast_path/4096

  • 🟩 execution_time [-6.586ns; -6.396ns] or [-6.361%; -6.178%]

scenario:alloc_free/sampled_system_slow_path/4096

  • 🟩 execution_time [-8.857ns; -8.765ns] or [-5.611%; -5.553%]

scenario:alloc_free/system/4096

  • 🟥 execution_time [+12.382ns; +12.569ns] or [+13.118%; +13.316%]

scenario:datadog_sample_span/resource_pattern_rule_not_matching/wall_time

  • 🟥 execution_time [+14.196ns; +14.384ns] or [+9.024%; +9.144%]

scenario:glob_matcher/ascii_exact_match/wall_time

  • 🟩 execution_time [-2.519ns; -2.470ns] or [-8.377%; -8.215%]

scenario:receiver_entry_point/report/2644

  • 🟥 execution_time [+193.601µs; +201.236µs] or [+5.375%; +5.587%]

Candidate

Omitted due to size.

Baseline

Omitted due to size.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 011c154962

ℹ️ 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".

for module in modules.into_iter().take(actual_module_count) {
// SAFETY: module was returned by K32EnumProcessModules and the symbol name is
// NUL-terminated.
let symbol = unsafe { GetProcAddress(module, c"otel_process_ctx_v2".as_ptr().cast()) };

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Export the Windows context symbol

On Windows this path only searches each module's PE export table via GetProcAddress (reader/windows.rs:105). The writer symbol is only #[no_mangle]; when libdd is consumed as a staticlib and linked into another executable/DLL, that does not create a PE export, so a reader built without process-context-writer cannot discover metadata published by the static writer and reports NotFound. Please add the same kind of export directive/dllexport for the production symbol that the test has to add explicitly.

Useful? React with 👍 / 👎.

Comment on lines +82 to +83
fn make_discoverable(&mut self) {
otel_process_ctx_v2.store(self.start_addr.as_ptr().cast(), Ordering::Release);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Clear stale macOS context pointers after fork

On macOS, when minherit(..., VM_INHERIT_NONE) succeeds, a forked child does not inherit the mmap but it does inherit this non-null atomic pointer. reader/macos.rs::discover_header treats any non-null value as published, so a child that creates a reader before republishing caches an unmapped address and read() returns the retryable EFAULT/WouldBlock path instead of NotFound. Forking runtimes can then spin on a context that can never become readable until something republishes; clear or validate the exported pointer after fork before making it discoverable.

Useful? React with 👍 / 👎.

Comment thread libdd-library-config/src/lib.rs Outdated
target_os = "linux",
any(feature = "process-context-reader", feature = "process-context-writer")
))]
#[cfg(any(feature = "process-context-reader", feature = "process-context-writer"))]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep process context gated to supported OSes

With process-context-writer still enabled by default, this now compiles otel_process_ctx on every target, but the module only defines the writer/reader platform types for Linux, macOS, and Windows. Any default-feature build of libdd-library-config for another target now fails at compile time instead of simply omitting process-context support as before; please keep this top-level cfg restricted to the OSes with implementations or add fallback stubs.

Useful? React with 👍 / 👎.

@cataphract cataphract force-pushed the glopes/otel-process-ctx-macos-windows branch from 011c154 to 7c33bad Compare July 14, 2026 18:20
@cataphract cataphract force-pushed the glopes/otel-process-ctx-linux-update branch from e5a142d to a9e0f0e Compare July 14, 2026 18:20
@datadog-datadog-prod-us1

datadog-datadog-prod-us1 Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Tests

🎉 All green!

🧪 All tests passed
❄️ No new flaky tests detected

🎯 Code Coverage (details)
Patch Coverage: 100.00%
Overall Coverage: 74.49% (+0.02%)

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: 954186b | Docs | Datadog PR Page | Give us feedback!

@cataphract cataphract requested a review from a team as a code owner July 14, 2026 22:06
@dd-octo-sts

dd-octo-sts Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Artifact Size Benchmark Report

aarch64-alpine-linux-musl
Artifact Baseline Commit Change
/aarch64-alpine-linux-musl/lib/libdatadog_profiling.a 86.15 MB 86.16 MB +.01% (+9.56 KB) 🔍
/aarch64-alpine-linux-musl/lib/libdatadog_profiling.so 7.88 MB 7.88 MB 0% (0 B) 👌
aarch64-unknown-linux-gnu
Artifact Baseline Commit Change
/aarch64-unknown-linux-gnu/lib/libdatadog_profiling.a 97.40 MB 97.41 MB +.01% (+10.99 KB) 🔍
/aarch64-unknown-linux-gnu/lib/libdatadog_profiling.so 10.62 MB 10.62 MB +0% (+88 B) 👌
libdatadog-x64-windows
Artifact Baseline Commit Change
/libdatadog-x64-windows/debug/dynamic/datadog_profiling_ffi.dll 25.54 MB 25.59 MB +.18% (+49.50 KB) 🔍
/libdatadog-x64-windows/debug/dynamic/datadog_profiling_ffi.lib 88.44 KB 88.66 KB +.25% (+234 B) 🔍
/libdatadog-x64-windows/debug/dynamic/datadog_profiling_ffi.pdb 185.33 MB 185.83 MB +.27% (+520.00 KB) 🔍
/libdatadog-x64-windows/debug/static/datadog_profiling_ffi.lib 957.25 MB 958.81 MB +.16% (+1.56 MB) 🔍
/libdatadog-x64-windows/release/dynamic/datadog_profiling_ffi.dll 8.35 MB 8.36 MB +.15% (+13.50 KB) 🔍
/libdatadog-x64-windows/release/dynamic/datadog_profiling_ffi.lib 88.44 KB 88.66 KB +.25% (+234 B) 🔍
/libdatadog-x64-windows/release/dynamic/datadog_profiling_ffi.pdb 24.72 MB 24.76 MB +.18% (+48.00 KB) 🔍
/libdatadog-x64-windows/release/static/datadog_profiling_ffi.lib 49.21 MB 49.28 MB +.13% (+70.44 KB) 🔍
libdatadog-x86-windows
Artifact Baseline Commit Change
/libdatadog-x86-windows/debug/dynamic/datadog_profiling_ffi.dll 22.19 MB 22.24 MB +.21% (+50.00 KB) 🔍
/libdatadog-x86-windows/debug/dynamic/datadog_profiling_ffi.lib 89.82 KB 90.06 KB +.26% (+240 B) 🔍
/libdatadog-x86-windows/debug/dynamic/datadog_profiling_ffi.pdb 189.78 MB 190.29 MB +.26% (+520.00 KB) 🔍
/libdatadog-x86-windows/debug/static/datadog_profiling_ffi.lib 945.93 MB 947.51 MB +.16% (+1.57 MB) 🔍
/libdatadog-x86-windows/release/dynamic/datadog_profiling_ffi.dll 6.46 MB 6.47 MB +.14% (+9.50 KB) 🔍
/libdatadog-x86-windows/release/dynamic/datadog_profiling_ffi.lib 89.82 KB 90.06 KB +.26% (+240 B) 🔍
/libdatadog-x86-windows/release/dynamic/datadog_profiling_ffi.pdb 26.54 MB 26.58 MB +.17% (+48.00 KB) 🔍
/libdatadog-x86-windows/release/static/datadog_profiling_ffi.lib 46.82 MB 46.89 MB +.14% (+67.71 KB) 🔍
x86_64-alpine-linux-musl
Artifact Baseline Commit Change
/x86_64-alpine-linux-musl/lib/libdatadog_profiling.a 76.96 MB 76.97 MB +0% (+5.83 KB) 👌
/x86_64-alpine-linux-musl/lib/libdatadog_profiling.so 8.81 MB 8.81 MB 0% (0 B) 👌
x86_64-unknown-linux-gnu
Artifact Baseline Commit Change
/x86_64-unknown-linux-gnu/lib/libdatadog_profiling.a 92.37 MB 92.38 MB +0% (+5.38 KB) 👌
/x86_64-unknown-linux-gnu/lib/libdatadog_profiling.so 10.72 MB 10.72 MB +.03% (+3.79 KB) 🔍

@cataphract cataphract force-pushed the glopes/otel-process-ctx-linux-update branch from a9e0f0e to 97138bc Compare July 14, 2026 23:05
@cataphract cataphract force-pushed the glopes/otel-process-ctx-macos-windows branch from 7122e8d to 954186b Compare July 14, 2026 23:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant