Skip to content

feat!: 1.0 - #2196

Open
jpnurmi wants to merge 50 commits into
masterfrom
v1
Open

jpnurmi wants to merge 50 commits into
masterfrom
v1

Conversation

@jpnurmi

@jpnurmi jpnurmi commented Oct 14, 2026 •

Copy link
Copy Markdown
Collaborator

Warning

WIP    🚧🔨⏳⛔

Close: #2044

#skip-changelog (WIP)

Run CI on `v1` like on `master`, and dispatch console compatibility
checks to the same-named console branch for commits cut from `v1`.

@cursor cursor 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.

Stale Bugbot comment from a previous run.

Comment thread .github/workflows/console-check.yml Resolved
@codecov

codecov Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 76.89791% with 706 lines in your changes missing coverage. Please review.
✅ Project coverage is 75.98%. Comparing base (b99f526) to head (341a1c2).
⚠️ Report is 5 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #2196      +/-   ##
==========================================
+ Coverage   75.71%   75.98%   +0.26%     
==========================================
  Files         103      104       +1     
  Lines       28316    29977    +1661     
  Branches     5208     5559     +351     
==========================================
+ Hits        21439    22777    +1338     
- Misses       5529     5808     +279     
- Partials     1348     1392      +44     
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

The collective PR runs CI on every push to v1 already.

@cursor cursor 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.

Stale Bugbot comment from a previous run.

Comment thread .github/workflows/codeql.yml Resolved
Pull request analyses are stored against the merge ref, so PRs into v1
had no baseline and compared against master.
* ci: include version in the release archive name

Fixes: #745

* ci: keep a stable archive name for latest downloads

Create a `sentry-native.zip` copy for the GCS `latest/` path so each
release replaces the same object. Keep versioned archive names for
GitHub and version-specific GCS paths.
BREAKING CHANGE: Linux, macOS, and Windows builds now default to the
`native` backend instead of `crashpad`.
The custom capture hook required private SDK types, while screenshot
options were still experimental.

BREAKING CHANGE: Implement sentry_screenshot_capture(const char *,
uint32_t), returning 0 on success.
The factory used a private-style `sentry__`-prefixed name even though
custom transports must provide its implementation. Give it a public-style
name and document the contract for custom implementations.

BREAKING CHANGE: Custom transport implementations must define:
```
sentry_transport_t *sentry_transport_new_default(void)
```

@cursor cursor 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.

Stale Bugbot comment from a previous run.

Comment thread src/sentry_options.c Resolved
Keep the scope write lock across a batch while allowing the owning thread
to use existing scope accessors without relocking. Defer backend scope
flushes until the outermost batch completes.
Split the existing global scope into an internal, read-only global
scope for SDK/OS metadata and configured defaults, and a mutable
isolation scope used by top-level APIs. Move user data, observers, and
backend flushing to the isolation scope.

Add `sentry_scope_acquire()` and `sentry_scope_release()` for direct
isolation scope access.

Implement Sentry's three-scope model with global -> isolation -> local
scope layering. Retain parent references and merge layers when preparing
events, telemetry, and attachments. Local values take precedence over
isolation and global defaults.

The SDK follows the global mode used by other Sentry SDKs for client
applications: all threads share the same process-wide isolation scope.
Changes made through top-level APIs or an acquired reference are shared
across all threads.

See:
- https://develop.sentry.dev/sdk/foundations/state-management/scopes/#isolation-scope

@cursor cursor 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.

Stale Bugbot comment from a previous run.

Comment thread src/sentry_scope.c Resolved
Provide exception metadata, registers, and a basic crashing-thread stack
for crash identification in native `on_crash`, matching `inproc`.
Use the same payload for `before_send` when `on_crash` is unset.

- Capture up to 128 fault-context IPs and unwind source in shared memory.
  Retain the faulting IP when available.
- Linux: SDK `libunwind` with signal-safe logging.
- macOS: SDK frame-pointer walker, guarded Mach reads, PAC stripping,
  `__DARWIN_OPAQUE_ARM_THREAD_STATE64` accessors, and
  `instruction_addr_adjustment=none`.
- Android/Linux without `libunwind`: bounded frame-pointer capture via
  `process_vm_readv`; avoids `libunwindstack`'s C++ allocation.
- Windows: MSVC x64 `RtlLookupFunctionEntry`/`RtlVirtualUnwind` walking
  without DbgHelp; SP progress permits recursive frames.
  Frame-pointer capture on x86/ARM64 and other x64 builds.
- ARM32 frame-pointer fallbacks retain only the faulting IP.

The daemon reuses partial captures and enriches existing frames.
Preserve exception/register/frame edits and removals, and honor callback
rejection.
Promote the 5-6 years old module API, also used by downstream SDKs,
now that it's usable for direct Native SDK users for comparing frame
addresses with module ranges.

Ref: #2102
Ref: #2116

@cursor cursor 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.

Stale Bugbot comment from a previous run.

@cursor cursor 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.

Stale Bugbot comment from a previous run.

Skip Windows frame symbol lookup when symbolize_stacktraces is
disabled, including crash frames captured before daemon processing.
Add length-prefixed frames and app-to-daemon IPC based on Unix domain
stream socket pairs and an anonymous pipe on Windows.

Ref: #1834
* perf(native): Sync scope over IPC

Instead of flushing the whole scope/event on disk on every scope
change, send an initial scope snapshot and then minimal incremental
updates to the crash daemon over IPC.

Keep the latest complete state in daemon memory for crash reports.
Discard interrupted messages and preserve crash callback changes through
a final event and attachment snapshot.

Close: #1834

* handle SENTRY_CRASH_STATE_CRASHING

* signal.h

@cursor cursor 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.

Stale Bugbot comment from a previous run.

@jpnurmi jpnurmi added the v1 Targets 1.0 (v1 branch) label Oct 16, 2026

@cursor cursor 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.

Stale Bugbot comment from a previous run.

The inproc-based Android NDK uses `SENTRY_TRANSPORT=none` and installs
a JNI function transport that writes to `outbox/`, leaving HTTP delivery
to Java. Tests substitute it with an stdout callback to inspect envelopes
without Java or HTTP.

However, the Native daemon in #1725 cannot use the function transport
from the separate daemon process. Provide (an internal) built-in stdout
transport (`SENTRY_TRANSPORT=stdout`) that both the SDK and daemon can
instantiate. This is mostly for out own integration testing purposes,
but it's also super handy for quick experiments:

```sh
$ make build SENTRY_BACKEND=inproc SENTRY_TRANSPORT=stdout
...
$ ./build/sentry_example_crash
...
[sentry] DEBUG sending envelope
{"event_id":"0e1d5355-5ba8-42cb-9e96-c6610d4ee9c1",...}
{"type":"event","length":2823}
{"event_id":"0e1d5355-5ba8-42cb-9e96-c6610d4ee9c1","timestamp":"2026-10-16T16:19:26.968633Z","platform":"native","level":"fatal","exception":...}
[sentry] INFO entering signal handler
...
```

@cursor cursor 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.

Stale Bugbot comment from a previous run.

* fix(native): group proc maps modules by load

`capture_modules_from_proc_maps()` merged all mappings of a file into
one module, producing oversized, overlapping images when a file is
mapped more than once. This is common on Android, for example an APK
that backs several native libraries. Keying by path and
`start - offset` instead splits libraries whose segments differ in
`p_vaddr - p_offset`, such as `libm.so.6` on x86_64 Linux.

Start a new module at a mapping with offset 0 unless the file was
captured last, which keeps small libraries that map every segment at
offset 0 together. Other mappings extend the file's most recent
module.

Skip non-readable mappings and mappings whose offset exceeds their
start address.

Enable the `debug_meta` overlap check of the native crash tests on
Linux.

* Update CHANGELOG.md
Move the Android API < 23 syscall fallback from the module finder into
`sentry__process_vm_readv()` in `sentry_os.c`, and use it in the module
finder, the native minidump writer, and the crash daemon stack reader.
Remove obsolete implementations and legacy user-report tests. List
replacements and migration details in the v1 changelog.

BREAKING CHANGE: Deprecated public APIs are no longer available.
The Android API 35 job failed before emulator startup:

> Warning: An error occurred while preparing SDK package Google APIs Intel
> x86_64 Atom System Image: dl.google.com.
> ...
> error: could not connect to TCP port 5554: Connection refused

https://github.com/getsentry/sentry-native/actions/runs/39443426624/job/118698972826

Retry SDK installation and emulator startup failures once while keeping
failures after boot fatal on the original test step.

Use smaller AOSP images to reduce setup downloads. The tests do not use
Google Play services, and the API 35 x86_64 image is about 780 MB instead
of 1.7 GB. Both variants still come from `dl.google.com`, so retries remain
necessary for transient download failures.

@cursor cursor 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.

Stale Bugbot comment from a previous run.

Comment thread .github/workflows/ci.yml Resolved
The daemon logs from both its main thread and the transport worker
thread, but `daemon_file_logger` used `localtime`, which shares a
static result buffer and re-runs `tzset` on every call. Under TSAN,
the resulting race report in the worker thread could deadlock against
the main thread priming libunwind inside `dl_iterate_phdr`, hanging
the daemon before it entered its main loop.

Keep `localtime` on Windows, where the CRT result is thread-local.
`sentry__usec_time_to_iso8601` omits the fractional part when the
microseconds are zero, which is valid RFC 3339. The transaction tests
parsed timestamps with a fixed `%Y-%m-%dT%H:%M:%S.%fZ` format and
failed whenever a timestamp landed exactly on a whole second. Parse
them with `datetime.fromisoformat` instead, as `assertions.py` already
does.
Deploy the selected crash handler beside `sentry_test_unit` so unit-only
builds work with the default hierarchical output layout. Run CTest unit
cases serially because they share filesystem fixtures.

Allow `make test-unit` and `make test-leaks` to select `SENTRY_BACKEND`
and `SENTRY_TRANSPORT`, preserving `none` as the default backend. This
allows resuing the convenient ready-made targets for any backend and
transport combination.

Close: #2215

@cursor cursor 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.

Stale Bugbot comment from a previous run.

Comment thread tests/unit/CMakeLists.txt Resolved
* feat: add `sentry_scope_set_trace`

Add `sentry_scope_set_trace()` and `sentry_scope_set_trace_n()` to set
the trace on a given scope, so that a local scope can carry a distinct
trace for a concurrent unit of work. The global `sentry_set_trace_n()`
now forwards to the scope-level setter.

* fix: use the capture scope's DSC for event envelopes

Scoped event and feedback capture apply the given scope to the event
payload, but `sentry__envelope_add_event()` read the dynamic sampling
context (DSC) and the propagation context's `sample_rand` from the
isolation scope through `SENTRY_WITH_SCOPE`. Since
`sentry_scope_set_trace()` lets a local scope carry its own
propagation context and DSC, such an envelope mixed metadata from two
scopes:

- the event's trace context came from the local scope,
- the header's `trace_id` matched, because it is copied from the
  event payload,
- `sample_rand`, `sampled`, `release` and `environment` came from the
  isolation scope.

For example, with a `traces_sample_rate` of 0.5, an isolation scope
with a `sample_rand` of 0.25 and a local scope with 0.75, scoped
capture sent `sampled: "true"` instead of the local scope's `"false"`.
Feedback was affected the same way, because
`sentry__envelope_add_feedback_event()` delegates to
`sentry__envelope_add_event()`.

Other Sentry SDKs avoid this by computing the DSC from the scope that
is applied to the event and carrying it on the event as SDK-internal
data, which the envelope builder moves into the header:

- sentry-go stores it in `event.sdkMetaData.dsc` from
  `Scope.ApplyToEvent`,
- sentry-php stores it in the event's SDK metadata from
  `Scope::applyToEvent`,
- sentry-javascript stores it in `event.sdkProcessingMetadata`,
- sentry-dotnet stores it in an internal
  `SentryEvent.DynamicSamplingContext`,
- sentry-python stores it in `contexts.trace.dynamic_sampling_context`,
  which the client pops before building the envelope.

In all of them the envelope is a plain container that never looks up
a scope.

Follow the same pattern: when the new `SENTRY_SCOPE_DSC` mode is set,
`sentry__scope_apply_to_event()` stamps the DSC on non-transaction
events under an internal `dsc` key, and `sentry__envelope_add_event()`
removes it from the payload and uses it as the `trace` header. The
envelope no longer reads any scope or options.

The mode is opt-in because not every scope-applied event goes through
`sentry__envelope_add_event()`. Crashpad's handler uploads the on-disk
`__sentry-event` directly, and the native backend's daemon writes its
own envelopes. Relay reports unknown top-level event attributes as
invalid, so those paths apply their scopes without the mode.
`SENTRY_SCOPE_ALL` includes it, which covers `sentry__prepare_event()`,
and feedback requests it explicitly.

As a result, crashpad envelopes built from reports in a later run no
longer get a `trace` header from that run's isolation scope, which
never described the crash.

* test: add integration test for scoped trace propagation

Capture an event with a local scope whose trace is set with
`sentry_scope_set_trace()`, while the isolation scope carries a
different trace, and check that both the event's trace context and
the envelope `trace` header come from the local scope. The header's
`sample_rand` must match the event's. Before the DSC was taken from
the capture scope, it came from the isolation scope instead.

* Update CHANGELOG.md
* feat: add `sentry_continue_trace`

Add `sentry_continue_trace()`, `sentry_scope_continue_trace()` and
their `_n` variants to continue a trace from incoming `sentry-trace`
and `baggage` headers without starting a transaction, as required by
the trace propagation spec's `continueTrace`.

The headers are parsed with the same code as
`sentry_transaction_context_update_from_header()`. When strict trace
continuation allows it, the scope's propagation context takes the
incoming trace and parent span IDs, sampling decision and
`sample_rand`, and the incoming baggage is frozen as the DSC.
Otherwise, a new trace is started. Like with `sentry_set_trace()`,
transactions no longer act as trace boundaries afterwards.

Per the spec, a missing `sentry-sample_rand` is derived from the
incoming `sample_rate` and sampling decision, transactions started
afterwards inherit the sampling decision, and the DSC of error events
reports it instead of recomputing `sampled` from the local sample
rate.

* Update CHANGELOG.md

* fix: set/continue traces from the initial scope

`sentry_scope_continue_trace()` looked up the global options, which
are not installed yet while `sentry_init()` runs the initial scope
callback, so a trace continued from there was dropped. Take the
options from the scope chain instead, where the isolation scope
carries them already, and do the same in `sentry_scope_set_trace()`.

Also build the default DSC before running the initial scope callback,
so that it no longer overwrites a DSC frozen from incoming baggage.

* fix: continue traces on cloned scopes

A clone of the isolation scope has neither its own options nor a
parent that carries them, so `ref_options()` found none, which made
`sentry_scope_continue_trace()` a no-op on it and left the DSC stale
in `sentry_scope_set_trace()`. Fall back to the global options when
the scope chain carries none.
* feat: add `sentry_iter_trace_propagation_headers`

Add `sentry_iter_trace_propagation_headers()` and
`sentry_scope_iter_trace_propagation_headers()` to fetch the
`sentry-trace` and `baggage` headers for downstream services without
an active span, as required by the trace propagation spec's
`getTraceData`. Until now, only `sentry_span_iter_headers()` and
`sentry_transaction_iter_headers()` existed, so a trace could not be
propagated without tracing.

The headers come from the span or transaction bound to the scope, if
any, otherwise from the scope's propagation context. Without a span,
the sampling decision is deferred unless one was inherited with
`sentry_continue_trace()`. Per the spec, the `sentry-trace` header then
has no sampled flag and the SDK-built baggage has no `sentry-sampled`.
The scoped variant falls back to the parent scopes for what the scope
does not set.

Ref: #2050

* Update CHANGELOG.md
Run the integration fixture twice against Sentry: an upstream app
captures an event and prints its `sentry-trace` and `baggage` headers,
and a downstream app continues the trace from them and captures its
own event. Sentry must then report both events on the same trace,
with the upstream span as the downstream parent.

@cursor cursor 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.

Stale Bugbot comment from a previous run.

Comment thread src/sentry_envelope.c Resolved
jpnurmi and others added 7 commits October 26, 2026 14:53
The scope loaders for `tags`, `extra`, `contexts`, `attributes`, and
`propagation_context` cloned the scope's own values before checking
whether there were any. For an empty scope, the clone was freed right
away, and the parent's values were returned instead. Every empty level
still paid for allocating and freeing a `thing_t` handle for the empty
value clone.

Clone the values only when the scope has any or has no parent. An
empty scope now returns the values loaded from its parent as is. The
TODOs about optimizing merges into empty destinations are removed,
because an empty scope no longer clones or merges anything.

Measured against v1 (e42bdcb) with a root parent and a child scope on
a pinned core, with CPU frequency scaling enabled, as the median CPU
time of 40 samples per case:

Values       Parent  Child  Before          After           Improvement
strings [1]  0       0      36.7-37.2 ns    20.3-20.7 ns    44.1-45.6%
objects [2]  0       0      36.3-36.5 ns    20.4-20.5 ns    43.7-44.0%
strings [1]  10      0      42.3-42.7 ns    25.3-25.7 ns    39.5-40.1%
objects [2]  10      0      426.7-468.6 ns  411.8-457.4 ns  2.4-3.5%
strings [1]  0       10     43.4-44.1 ns    43.9-44.1 ns    ~0%
objects [2]  0       10     417.6-482.8 ns  421.3-474.4 ns  ~0%
strings [1]  10      10     1626-1653 ns    1644-1667 ns    ~0%
objects [2]  10      10     2468-2575 ns    2474-2562 ns    ~0%

[1] `tags`, `extra`, `propagation_context`
[2] `contexts`, `attributes`
…2241)

* Report host OS context under Wine and Proton

Under Wine, build the OS context from the host via wine_get_host_version and the host os-release read through the Z: drive, in the same shape as the native Linux OS context. Prefer /run/host to report the host instead of the Steam Runtime or Flatpak container.

* Update changelog

* Expect host OS context in Wine integration tests

* Clean up

* Update CHANGELOG to remove 'Features' section

Removed the 'Features' section from the CHANGELOG.

* Prefer host os-release on native Linux

* Report SteamOS and Bazzite as the OS name

* Expect named OS context in Linux test assertions
* feat(native): Support ELF modules at non-zero file offsets

The minidump writer and `capture_modules_from_proc_maps()` grouped
`/proc/<pid>/maps` entries by file name and expected an ELF header at
offset 0. An ELF image can also start inside a larger file, such as an
uncompressed library that Android maps straight from an APK, and such
images were dropped from the module list.

Start a module at each mapping whose file offset holds an ELF header,
group the image's other segments by its load range, and read the build
ID, size, and SONAME at that offset. Move
`compute_elf_size_from_phdrs()` to `sentry_elf.h` to share it.

This prepares the native backend for Android, where AGP's default
packaging maps every app library from the APK.

Ref: #1725

* fix(native): Apply the ELF offset to the build ID section headers

The previous commit adjusted the section header offset in
`elf_locate_symtab()` instead of `extract_elf_build_id_for_module()`,
where `elf_offset` is not declared, so the crash daemon failed to
compile. Move the adjustment to where the build ID is read.

* fix(native): Keep embedded ELFs mapped below their file offset

The `offset > start` guard in `capture_modules_from_proc_maps()` dropped
mappings before an ELF image inside a larger file could be detected.
The guard only protects the `start - offset` load base of a regular ELF
file, so apply it there instead.
The crash daemon could only unwind the threads that did not crash with
`libunwind_remote`, which Android builds lack because they use
libunwindstack. Add a `libunwindstack_remote` backend, compiled in only
with the native backend, that attaches to a thread with ptrace, reads
its registers with `Regs::RemoteGet()`, and unwinds it. Share the
ptrace attach loop with `libunwind_remote`.

This prepares the native backend for Android.
* feat(native): Support ELF modules at non-zero file offsets

The minidump writer and `capture_modules_from_proc_maps()` grouped
`/proc/<pid>/maps` entries by file name and expected an ELF header at
offset 0. An ELF image can also start inside a larger file, such as an
uncompressed library that Android maps straight from an APK, and such
images were dropped from the module list.

Start a module at each mapping whose file offset holds an ELF header,
group the image's other segments by its load range, and read the build
ID, size, and SONAME at that offset. Move
`compute_elf_size_from_phdrs()` to `sentry_elf.h` to share it.

This prepares the native backend for Android, where AGP's default
packaging maps every app library from the APK.

Ref: #1725

* fix(native): Apply the ELF offset to the build ID section headers

The previous commit adjusted the section header offset in
`elf_locate_symtab()` instead of `extract_elf_build_id_for_module()`,
where `elf_offset` is not declared, so the crash daemon failed to
compile. Move the adjustment to where the build ID is read.

* fix(native): Keep embedded ELFs mapped below their file offset

The `offset > start` guard in `capture_modules_from_proc_maps()` dropped
mappings before an ELF image inside a larger file could be detected.
The guard only protects the `start - offset` load base of a regular ELF
file, so apply it there instead.

* feat(unwinder): Unwind remote threads with libunwindstack

The crash daemon could only unwind the threads that did not crash with
`libunwind_remote`, which Android builds lack because they use
libunwindstack. Add a `libunwindstack_remote` backend, compiled in only
with the native backend, that attaches to a thread with ptrace, reads
its registers with `Regs::RemoteGet()`, and unwinds it. Share the
ptrace attach loop with `libunwind_remote`.

This prepares the native backend for Android.

* feat(native): Support preloading the crash handler

`sentry__backend_preload()` was a no-op for the native backend. Install
its signal handlers early, so that they keep their place in the signal
chain ahead of a managed runtime, and let a later `sentry_init()` adopt
them. Like with `inproc`, shutdown keeps the preloaded handlers
installed, forwarding crashes to the previous handlers until the next
initialization.

@cursor cursor 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.

Stale Bugbot comment from a previous run.

Before `sentry_init()` and after `sentry_close()`, preloaded handlers
are only a placeholder in the signal chain. A signal that reached them
restored the previous handlers but left `g_handlers_installed` and
`g_preloaded` set, so a later `sentry_init()` took the early return and
never reinstalled the crash handler. The fall-through also re-raised
the signal after the previous handler returned, killing the process
even if a handler installed before the preload had recovered from it.

Like the inproc backend, consume the preload state before forwarding
the signal, and return to wherever the previous handler left off
instead of re-raising. Re-raise only when the signal had its default
action before the preload.

@cursor cursor 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.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit a4a98f3. Configure here.

jpnurmi and others added 5 commits October 29, 2026 15:00
Threads enumerated from `/proc/<pid>/task` have no saved registers, so
the daemon called `process_vm_readv` at stack address 0 for each of
them. The read always failed and logged before the remote unwinder
took over.

Skip the read when the stack pointer is unknown, and include `errno`
in the remaining `process_vm_readv` and thread enumeration failures.
…2273)

Allow `SENTRY_HANDLER_STRATEGY_CHAIN_AT_START` in the native backend on
Android, as in the inproc backend, so that a signal that Mono turns into
a managed exception, such as a `NullReferenceException`, is not captured
as a native crash.

As in the inproc backend, fall back to the default strategy below API
26, where debuggerd kills the process after the chained handler runs.

This prepares the native backend for Android support (#1725).
* feat(linux): RISC-V support

Support register capture, stack unwinding, ELF metadata, and native
minidump generation.

* Update CHANGELOG.md

* context.version

* llvm

* setup-qemu-action for riscv64

* tweak skip conditions

* gcc < 14

* ci: restore qemu-user for Arm32

* clarify & restore original phrasing
* feat: Add pkg-config support

- Added support for generating and installing a .pc file for pkg-config
- Controlled by the SENTRY_INSTALL_PKGCONFIG CMake option
- Uses CMAKE_INSTALL_LIBDIR and CMAKE_INSTALL_INCLUDEDIR to support non-standard layouts (e.g., lib64)
- Installs the generated file to the standard pkg-config directory

* feat(pkgconfig): Expose the installed binary directory

Export `bindir` in `sentry.pc` so consumers can locate the installed
crash handler. Honor `CMAKE_INSTALL_BINDIR` when installing the native
handler and its Windows companion so the metadata matches the layout.

Add a standalone consumer that links through pkg-config and initializes
the default backend using the installed handler and a writable database
directory.

* copy what inproc_stress_test does

* fix(pkgconfig): Install sentry.pc only for shared builds

A static `libsentry` needs its full private link graph, including
vendored backend archives, system libraries and the C++ runtime. The
CMake package already exports that graph. Install `sentry.pc` only for
shared builds, where `-lsentry` is complete.

---------

Co-authored-by: J-P Nurmi <jpnurmi@gmail.com>
Running the native backend tests on Android also enabled
`test_pkgconfig`, which expects a desktop install. Android builds have
no versioned `libsentry.so` symlinks, macOS hosts look for a `.dylib`,
and the consumer would have to run on the device. Skip it like
`test_shared_lib`.

This branch has not been deployed

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

Labels

v1 Targets 1.0 (v1 branch)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1.0

3 participants