Skip to content

feat: Sentry native crash backend#1433

Open
mujacica wants to merge 132 commits intomasterfrom
feat/sentry_native_backend
Open

feat: Sentry native crash backend#1433
mujacica wants to merge 132 commits intomasterfrom
feat/sentry_native_backend

Conversation

@mujacica
Copy link
Contributor

  • Sentry native crash backend
  • Out-of-process daemon/handler
  • MacOS/Android/Windows/Linux support
  • Integration with external crash reporter
  • IPC/SHM/Signaling multi-platform implementation
  • Minidump writers for all platforms
  • In-process option (process_crash function)
  • Different options for Minidump sizes
  • Full sentry-codebase integration
  • Sentry logger integration
  • Sentry debug-flags integration

@mujacica
Copy link
Contributor Author

@sentry review

1 similar comment
@mujacica
Copy link
Contributor Author

@sentry review

@mujacica mujacica force-pushed the feat/sentry_native_backend branch from 216b3cd to e4cd98c Compare January 15, 2026 10:28
@mujacica
Copy link
Contributor Author

@sentry review

@mujacica
Copy link
Contributor Author

@cursor review

@mujacica
Copy link
Contributor Author

@cursor review

@mujacica mujacica force-pushed the feat/sentry_native_backend branch from d634773 to eb77775 Compare January 15, 2026 19:37
@mujacica
Copy link
Contributor Author

@sentry review

@mujacica mujacica force-pushed the feat/sentry_native_backend branch from d46d50a to d38b5e1 Compare January 17, 2026 08:10
@mujacica mujacica marked this pull request as ready for review January 17, 2026 11:50
cursor[bot]

This comment was marked as outdated.

cursor[bot]

This comment was marked as outdated.

cursor[bot]

This comment was marked as outdated.

@mujacica mujacica force-pushed the feat/sentry_native_backend branch from d33258f to 71ea60d Compare January 20, 2026 10:01
@mujacica mujacica changed the title (POC) feat: Sentry native crash backend feat: Sentry native crash backend Jan 20, 2026
@github-actions
Copy link

github-actions bot commented Jan 20, 2026

Messages
📖 Do not forget to update Sentry-docs with your feature once the pull request gets approved.

Generated by 🚫 dangerJS against 350483c

@linear
Copy link

linear bot commented Feb 5, 2026

@mujacica mujacica force-pushed the feat/sentry_native_backend branch from 79d2b05 to a6af7d6 Compare February 5, 2026 09:54
…ash tests

- Fix Windows daemon start failure going undetected: pid_t is DWORD
  (unsigned) so (pid_t)-1 == 0xFFFFFFFF, not 0
- Add metrics flush on crash to native backend (matching inproc/breakpad/crashpad)
- Add native backend to test_metrics_on_crash parametrization
- Move test_native_logs_on_crash to test_integration_logs.py with other
  backend-specific crash log tests
- Clean up unused imports in test_integration_http.py

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@mujacica mujacica force-pushed the feat/sentry_native_backend branch from ac05d84 to c02a12f Compare March 2, 2026 11:48
mujacica and others added 2 commits March 2, 2026 12:50
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The sentry-crash daemon was using undefined LIBUNWIND_INCLUDE_DIR and
LIBUNWIND_LIBRARIES variables instead of linking to the vendored
`unwind` CMake target. This caused a missing libunwind.h build failure.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link

@cursor cursor bot left a comment

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 3 potential issues.

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

- Fix ARM64 minidump context: fpcr must precede fpsr per the Windows
  ARM64_NT_CONTEXT specification.
- Fix Linux ptrace: attach to crashed_tid instead of crashed_pid so
  PTRACE_GETFPREGS works for non-main thread crashes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link

@cursor cursor bot left a comment

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 3 potential issues.

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

SENTRY_WARN("write_minidump: directory write failed");
close(writer.fd);
return -1;
}
Copy link

Choose a reason for hiding this comment

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

macOS fallback path leaves partial files on error

Medium Severity

The macOS sentry__write_minidump fallback path (when task_for_pid fails, which is the common case without root/entitlements) has ~8 error returns that all do close(writer.fd); return -1; without calling unlink(output_path). This leaves partial/corrupt minidump files on disk. In contrast, the Linux writer and the macOS full path (cleanup_error label) consistently call unlink(output_path) on every error path. The caller in sentry_crash_daemon.c also doesn't clean up the file on failure — it only clears the path string.

Fix in Cursor Fix in Web

if (!stack_buffer) {
*stack_size_out = 0;
return 0;
}
Copy link

Choose a reason for hiding this comment

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

Missing stack_start_out assignment on malloc failure path

Low Severity

In write_thread_stack, the malloc failure path sets *stack_size_out = 0 but does not set *stack_start_out = 0, unlike the read-failure path at line 955 which sets both. The callers happen to pre-initialize stack_start to 0, so this doesn't cause a practical issue today, but the inconsistency is fragile and could cause an uninitialized value to be used if a future caller doesn't pre-initialize.

Fix in Cursor Fix in Web

stack_end = writer->mappings[i].end;
break;
}
}
Copy link

Choose a reason for hiding this comment

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

Stack lookup misses non-main thread stacks on Linux

Medium Severity

write_thread_stack searches for the stack mapping by requiring strstr(name, "[stack") != NULL. On Linux, only the main thread's stack is labeled [stack] in /proc/pid/maps — non-main thread stacks are anonymous mappings with no name. This means the precise stack bounds are never found for any non-main thread, causing the code to always fall through to the heuristic fallback of SP + 512KB, potentially missing the actual stack top boundary.

Fix in Cursor Fix in Web

Copy link

@cursor cursor bot left a comment

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 3 potential issues.

Bugbot Autofix prepared fixes for all 3 issues found in the latest run.

  • ✅ Fixed: macOS fallback path leaves corrupt minidump files on disk
    • Added unlink(output_path) calls to all 10 error return paths in the macOS fallback code path to properly clean up partial/corrupt minidump files.
  • ✅ Fixed: Duplicate sources in sentry-crash executable build target
    • Removed explicit addition of sentry_crash_daemon.c and sentry_crash_ipc.c from CMakeLists.txt since they are already included via ${SENTRY_SOURCES}.
  • ✅ Fixed: Per-module fsync degrades crash minidump writing performance
    • Removed redundant fsync call inside the module loop since the final fsync after the loop ensures all data is committed.

Create PR

Or push these changes by commenting:

@cursor push f75e3461ae
Preview (f75e3461ae)
diff --git a/CMakeLists.txt b/CMakeLists.txt
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -752,8 +752,6 @@
 	# Create daemon executable with same sources plus daemon-specific files
 	add_executable(sentry-crash
 		${SENTRY_SOURCES}
-		src/backends/native/sentry_crash_daemon.c
-		src/backends/native/sentry_crash_ipc.c
 		src/backends/native/sentry_crash_context.h
 	)
 

diff --git a/src/backends/native/minidump/sentry_minidump_linux.c b/src/backends/native/minidump/sentry_minidump_linux.c
--- a/src/backends/native/minidump/sentry_minidump_linux.c
+++ b/src/backends/native/minidump/sentry_minidump_linux.c
@@ -1243,11 +1243,9 @@
                 ssize_t written2 = write(writer->fd, &cv_rva, sizeof(cv_rva));
 
                 if (written1 == sizeof(cv_size) && written2 == sizeof(cv_rva)) {
-                    // Force flush to disk
-                    fsync(writer->fd);
                     SENTRY_DEBUGF(
                         "  Updated module[%zu]: name_rva=0x%x, cv_rva=0x%x, "
-                        "cv_size=%u (flushed)",
+                        "cv_size=%u",
                         i, name_rva, cv_rva, cv_size);
                 } else {
                     SENTRY_WARNF("Failed to write CV record for module %zu: "

diff --git a/src/backends/native/minidump/sentry_minidump_macos.c b/src/backends/native/minidump/sentry_minidump_macos.c
--- a/src/backends/native/minidump/sentry_minidump_macos.c
+++ b/src/backends/native/minidump/sentry_minidump_macos.c
@@ -1013,6 +1013,7 @@
         if (lseek(writer.fd, writer.current_offset, SEEK_SET) < 0) {
             SENTRY_WARN("write_minidump: lseek failed");
             close(writer.fd);
+            unlink(output_path);
             return -1;
         }
 
@@ -1023,36 +1024,42 @@
         if (write_system_info_stream(&writer, &directories[0]) < 0) {
             SENTRY_WARN("write_minidump: system_info failed");
             close(writer.fd);
+            unlink(output_path);
             return -1;
         }
         SENTRY_DEBUG("write_minidump: writing misc_info stream");
         if (write_misc_info_stream(&writer, &directories[1]) < 0) {
             SENTRY_WARN("write_minidump: misc_info failed");
             close(writer.fd);
+            unlink(output_path);
             return -1;
         }
         SENTRY_DEBUG("write_minidump: writing thread_list stream");
         if (write_thread_list_stream(&writer, &directories[2]) < 0) {
             SENTRY_WARN("write_minidump: thread_list failed");
             close(writer.fd);
+            unlink(output_path);
             return -1;
         }
         SENTRY_DEBUG("write_minidump: writing exception stream");
         if (write_exception_stream(&writer, &directories[3]) < 0) {
             SENTRY_WARN("write_minidump: exception failed");
             close(writer.fd);
+            unlink(output_path);
             return -1;
         }
         SENTRY_DEBUG("write_minidump: writing module_list stream");
         if (write_module_list_stream(&writer, &directories[4]) < 0) {
             SENTRY_WARN("write_minidump: module_list failed");
             close(writer.fd);
+            unlink(output_path);
             return -1;
         }
         SENTRY_DEBUG("write_minidump: writing memory_list stream");
         if (write_memory_list_stream(&writer, &directories[5]) < 0) {
             SENTRY_WARN("write_minidump: memory_list failed");
             close(writer.fd);
+            unlink(output_path);
             return -1;
         }
         SENTRY_DEBUG("write_minidump: all streams written");
@@ -1062,6 +1069,7 @@
         if (lseek(writer.fd, 0, SEEK_SET) < 0) {
             SENTRY_WARN("write_minidump: lseek to beginning failed");
             close(writer.fd);
+            unlink(output_path);
             return -1;
         }
 
@@ -1076,6 +1084,7 @@
         if (write(writer.fd, &header, sizeof(header)) != sizeof(header)) {
             SENTRY_WARN("write_minidump: header write failed");
             close(writer.fd);
+            unlink(output_path);
             return -1;
         }
 
@@ -1085,6 +1094,7 @@
             != sizeof(directories)) {
             SENTRY_WARN("write_minidump: directory write failed");
             close(writer.fd);
+            unlink(output_path);
             return -1;
         }
This Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.

mujacica and others added 3 commits March 3, 2026 10:54
Fix clang-format violations in ARM64 PAC macros and register code.
Improve batcher flush logic: snapshot last_enqueue_ms before sleeping
and compare after waking to detect idle buffers, replacing the 2x
idle threshold that broke timer-based flush tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… drop per-module fsync

- macOS minidump fallback path: use goto cleanup to unlink partial files
  on error instead of just closing the fd, matching the full path behavior
- CMakeLists.txt: remove duplicate sentry_crash_daemon.c and
  sentry_crash_ipc.c from sentry-crash target (already in SENTRY_SOURCES)
- Linux minidump: remove per-module fsync inside module loop, keeping
  only the final fsync after all modules are written

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link

@cursor cursor bot left a comment

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 3 potential issues.

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

…er idle flush

- CMakeLists: copy all compile definitions from sentry target to
  sentry-crash daemon so shared sources compile under identical
  preprocessor conditions (backend, transport, unwinder, etc.)
- minidump_common: write header directly instead of via write_data to
  avoid corrupting current_offset when seeking back to position 0
- minidump_linux: add uint32_t RVA overflow guard before seek+patch loop
- batcher: replace snapshot-and-compare with idle time check (1s
  threshold) to correctly flush partial buffers that have been sitting
  idle, even when items were enqueued during the sleep period

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link

@cursor cursor bot left a comment

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 2 potential issues.

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

…ro stack_start_out on alloc failure

- current_offset was uint32_t, making the > UINT32_MAX check always
  false. Widening to uint64_t lets the guard actually detect overflow.
- write_thread_stack now zeros *stack_start_out on malloc failure,
  matching the macOS counterpart.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link

@cursor cursor bot left a comment

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.

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

… structs

The previous commit widened current_offset to uint64_t in the base
struct but not in the Linux/macOS platform structs, causing a layout
mismatch that corrupted the crash_ctx pointer on every write_data call.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link

@cursor cursor bot left a comment

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 2 potential issues.

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

…permissions

- aarch64 Linux: use struct field access (uctx->uc_mcontext.regs[i],
  .sp, .pc) instead of raw pointer indexing that skipped fault_address,
  causing every register value to be shifted by one
- Windows: request PROCESS_DUP_HANDLE when opening crashed process in
  FULL mode, needed for MiniDumpWithHandleData

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link

@cursor cursor bot left a comment

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 3 potential issues.

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

mujacica and others added 2 commits March 3, 2026 12:33
…rning on aarch64

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- write_data: seek back on partial write to keep fd position in sync
  with current_offset
- write_module_list_stream: bail early if initial module list write
  fails (rva==0) to prevent patching into header area
- thread_context.size: only set non-zero when write_thread_context
  succeeds, preventing invalid location descriptors pointing at
  offset 0 (Linux and macOS, 5 locations)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link

@cursor cursor bot left a comment

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 3 potential issues.

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

mujacica and others added 2 commits March 3, 2026 13:01
…g write sync

- Update thread_context.size after ptrace re-write in Linux minidump
  writer so it stays consistent with the RVA
- Validate bytes_read matches requested size in macOS read_task_memory
  to detect partial reads
- Seek back on partial padding write in write_data to keep fd position
  in sync with current_offset

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link

@cursor cursor bot left a comment

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 2 potential issues.

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

mujacica and others added 2 commits March 3, 2026 13:24
- macOS SMART mode now only captures the crash-address region instead of
  all readable+writable regions, matching Linux behavior and the ~5-10MB
  target documented in the API
- Cap per-region size to 4MB (was 64MB) to match Linux
- Add UINT32_MAX overflow check in write_data to prevent silent RVA
  truncation when minidumps exceed 4GB in FULL mode

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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.

3 participants