|
1 | 1 | // Copyright 2025-Present Datadog, Inc. https://www.datadoghq.com/ |
2 | 2 | // SPDX-License-Identifier: Apache-2.0 |
3 | 3 |
|
4 | | -//! Thin cdylib that wraps libdatadog's published `libdd-profiling-heap-gotter` |
5 | | -//! crate under stable, ddtrace-owned C symbols. The Python ctypes activator |
6 | | -//! (`ddtrace/internal/datadog/profiling/heap_gotter`) dlopen's the resulting |
7 | | -//! `libdd_heap_gotter.<ext-suffix>.so` and drives GOT-based native heap |
8 | | -//! profiling from it. |
9 | | -//! |
10 | | -//! The upstream crate exposes a pure-Rust API (`install_heap_overrides`, |
11 | | -//! `heap_overrides_are_installed`); it is not a C-ABI surface. Here we re-export |
12 | | -//! those calls as fixed, unmangled `extern "C"` entry points returning a plain |
13 | | -//! `bool`, so the Python ctypes side links against stable symbol names and gets |
14 | | -//! a trivial success signal. |
15 | | -//! |
16 | | -//! Installation is permanent and process-global: the GOT entries patched by |
17 | | -//! `install` point at functions inside the linked-in gotter code, so this |
18 | | -//! library must stay loaded for the life of the process. The Python activator |
19 | | -//! loads it into the global namespace and never unloads it. After `fork()` the |
20 | | -//! child inherits both the loaded library and the patched GOT, so a re-install |
21 | | -//! in the child is a harmless no-op. |
| 4 | +//! Thin cdylib wrapping `libdd-profiling-heap-gotter` (crates.io) under stable |
| 5 | +//! `extern "C"` symbols for the Python ctypes activator to dlopen. |
22 | 6 |
|
23 | 7 | /// Install GOT overrides for supported heap-allocation symbols and report |
24 | 8 | /// whether the install actually took effect. |
@@ -50,6 +34,29 @@ pub extern "C" fn ddtrace_heap_gotter_is_installed() -> bool { |
50 | 34 | libdd_profiling_heap_gotter::heap_overrides_are_installed() |
51 | 35 | } |
52 | 36 |
|
| 37 | +/// Set the mean sample distance (bytes between samples) for the heap sampler. |
| 38 | +/// Must be called before `ddtrace_heap_gotter_install` to take effect. |
| 39 | +/// |
| 40 | +/// # Safety |
| 41 | +/// |
| 42 | +/// C ABI entry point; always safe to call. |
| 43 | +#[no_mangle] |
| 44 | +pub extern "C" fn ddtrace_heap_gotter_set_sampling_distance(distance: u64) { |
| 45 | + libdd_profiling_heap_gotter::set_default_sampling_distance(distance); |
| 46 | +} |
| 47 | + |
| 48 | +/// Re-scan loaded libraries and patch any newly-introduced GOT entries. |
| 49 | +/// Normally called automatically from the internal `dlopen` hook; exposed here |
| 50 | +/// for cases where the Python side loads a `.so` and wants immediate coverage. |
| 51 | +/// |
| 52 | +/// # Safety |
| 53 | +/// |
| 54 | +/// C ABI entry point with no arguments and no pointers; always safe to call. |
| 55 | +#[no_mangle] |
| 56 | +pub extern "C" fn ddtrace_heap_gotter_update() { |
| 57 | + libdd_profiling_heap_gotter::update_heap_overrides(); |
| 58 | +} |
| 59 | + |
53 | 60 | /// Test-only: number of times a patched hook has run in this process. Lets |
54 | 61 | /// integration tests prove the patched GOT was actually exercised without a |
55 | 62 | /// live eBPF attach. Only present when built with the `test-support` feature; |
|
0 commit comments