Skip to content

fix(native): propagate transport options and handler path to crash daemon#1573

Open
mujacica wants to merge 4 commits intomasterfrom
fix/native-daemon-options-propagation
Open

fix(native): propagate transport options and handler path to crash daemon#1573
mujacica wants to merge 4 commits intomasterfrom
fix/native-daemon-options-propagation

Conversation

@mujacica
Copy link
Contributor

The native backend daemon was not receiving SSL certificate, proxy, user agent, or handler path settings from the parent process options. This caused SSL errors (curl code 60) when the daemon tried to upload crash reports, and required users to place the sentry-crash binary next to their executable instead of using sentry_options_set_handler_path.

Pass ca_certs, proxy, user_agent, and handler_path through the shared memory crash context so the daemon can configure its curl transport and find the sentry-crash executable correctly.

mujacica and others added 3 commits March 11, 2026 07:26
…emon

The native backend daemon was not receiving SSL certificate, proxy,
user agent, or handler path settings from the parent process options.
This caused SSL errors (curl code 60) when the daemon tried to upload
crash reports, and required users to place the sentry-crash binary
next to their executable instead of using sentry_options_set_handler_path.

Pass ca_certs, proxy, user_agent, and handler_path through the shared
memory crash context so the daemon can configure its curl transport
and find the sentry-crash executable correctly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@mujacica mujacica marked this pull request as ready for review March 12, 2026 16:42
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 prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Handler path stored in shared memory but unused by daemon
    • Removed handler_path field from shared memory and now pass it directly to daemon start function, saving SENTRY_CRASH_MAX_PATH bytes and simplifying the code.

Create PR

Or push these changes by commenting:

@cursor push da213bae28
Preview (da213bae28)
diff --git a/src/backends/native/sentry_crash_context.h b/src/backends/native/sentry_crash_context.h
--- a/src/backends/native/sentry_crash_context.h
+++ b/src/backends/native/sentry_crash_context.h
@@ -284,7 +284,6 @@
     char ca_certs[SENTRY_CRASH_MAX_PATH]; // CA certificates file path for SSL
     char proxy[SENTRY_CRASH_MAX_PATH]; // HTTP proxy URL
     char user_agent[256]; // User-Agent header for HTTP requests
-    char handler_path[SENTRY_CRASH_MAX_PATH]; // Path to sentry-crash executable
 
     // Minidump output path (filled by daemon)
     char minidump_path[SENTRY_CRASH_MAX_PATH];

diff --git a/src/backends/sentry_backend_native.c b/src/backends/sentry_backend_native.c
--- a/src/backends/sentry_backend_native.c
+++ b/src/backends/sentry_backend_native.c
@@ -234,18 +234,6 @@
 #endif
     }
 
-    // Store handler path for daemon executable lookup
-    if (options->handler_path) {
-#ifdef _WIN32
-        strncpy_s(ctx->handler_path, sizeof(ctx->handler_path),
-            options->handler_path->path, _TRUNCATE);
-#else
-        strncpy(ctx->handler_path, options->handler_path->path,
-            sizeof(ctx->handler_path) - 1);
-        ctx->handler_path[sizeof(ctx->handler_path) - 1] = '\0';
-#endif
-    }
-
     state->event_path = sentry__path_join_str(run_path, "__sentry-event");
     state->breadcrumb1_path
         = sentry__path_join_str(run_path, "__sentry-breadcrumb1");
@@ -330,9 +318,8 @@
 #else
     // Other platforms: Use out-of-process daemon
     // Pass the notification handles (eventfd/pipe on Unix, events on Windows)
-    // handler_path from crash context (empty string if not set by user)
     const char *daemon_handler_path
-        = ctx->handler_path[0] != '\0' ? ctx->handler_path : NULL;
+        = options->handler_path ? options->handler_path->path : NULL;
 #    if defined(SENTRY_PLATFORM_LINUX) || defined(SENTRY_PLATFORM_ANDROID)
     uint64_t tid = (uint64_t)pthread_self();
     state->daemon_pid = sentry__crash_daemon_start(getpid(), tid,

diff --git a/tests/unit/test_native_backend.c b/tests/unit/test_native_backend.c
--- a/tests/unit/test_native_backend.c
+++ b/tests/unit/test_native_backend.c
@@ -357,18 +357,11 @@
     ctx.user_agent[sizeof(ctx.user_agent) - 1] = '\0';
     TEST_CHECK_STRING_EQUAL(ctx.user_agent, test_ua);
 
-    // Verify handler_path field exists and can hold a typical path
-    const char *test_handler = "/usr/local/bin/sentry-crash";
-    strncpy(ctx.handler_path, test_handler, sizeof(ctx.handler_path) - 1);
-    ctx.handler_path[sizeof(ctx.handler_path) - 1] = '\0';
-    TEST_CHECK_STRING_EQUAL(ctx.handler_path, test_handler);
-
     // Verify fields are zero-initialized when memset to 0
     memset(&ctx, 0, sizeof(ctx));
     TEST_CHECK(ctx.ca_certs[0] == '\0');
     TEST_CHECK(ctx.proxy[0] == '\0');
     TEST_CHECK(ctx.user_agent[0] == '\0');
-    TEST_CHECK(ctx.handler_path[0] == '\0');
 #else
     SKIP_TEST();
 #endif
@@ -425,7 +418,10 @@
 }
 
 /**
- * Test that handler_path option is propagated to crash context
+ * Test that handler_path option is set correctly in options.
+ * Note: handler_path is now passed directly to the daemon start function
+ * instead of being stored in shared memory, since the daemon never reads
+ * it from shared memory.
  */
 SENTRY_TEST(crash_context_handler_path_propagation)
 {
@@ -435,25 +431,15 @@
     // Set handler path
     sentry_options_set_handler_path(options, "/opt/sentry/sentry-crash");
 
-    // Simulate what native_backend_startup does
-    sentry_crash_context_t ctx;
-    memset(&ctx, 0, sizeof(ctx));
+    // Verify handler_path option is set correctly
+    TEST_ASSERT(!!options->handler_path);
+    TEST_CHECK_STRING_EQUAL(
+        options->handler_path->path, "/opt/sentry/sentry-crash");
 
-    if (options->handler_path) {
-        strncpy(ctx.handler_path, options->handler_path->path,
-            sizeof(ctx.handler_path) - 1);
-        ctx.handler_path[sizeof(ctx.handler_path) - 1] = '\0';
-    }
-
-    TEST_CHECK_STRING_EQUAL(ctx.handler_path, "/opt/sentry/sentry-crash");
-
-    // Without handler_path set, field should remain empty
+    // Without handler_path set, it should be NULL
     sentry_options_t *options2 = sentry_options_new();
     TEST_ASSERT(!!options2);
-    sentry_crash_context_t ctx2;
-    memset(&ctx2, 0, sizeof(ctx2));
-    // Don't set handler_path - verify it stays empty
-    TEST_CHECK(ctx2.handler_path[0] == '\0');
+    TEST_CHECK(options2->handler_path == NULL);
 
     sentry_options_free(options);
     sentry_options_free(options2);
@@ -481,15 +467,10 @@
     if (options->proxy) {
         strncpy(ctx.proxy, options->proxy, sizeof(ctx.proxy) - 1);
     }
-    if (options->handler_path) {
-        strncpy(ctx.handler_path, options->handler_path->path,
-            sizeof(ctx.handler_path) - 1);
-    }
 
     // All should remain empty (zero-initialized)
     TEST_CHECK(ctx.ca_certs[0] == '\0');
     TEST_CHECK(ctx.proxy[0] == '\0');
-    TEST_CHECK(ctx.handler_path[0] == '\0');
 
     sentry_options_free(options);
 #else

This Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.

@mujacica
Copy link
Contributor Author

@cursor push da213ba

The handler_path field in sentry_crash_context_t was being written to
shared memory by the parent process but was never read by the daemon
process. The daemon only uses the handler_path parameter passed to
sentry__crash_daemon_start().

This change:
- Removes the handler_path field from sentry_crash_context_t, saving
  SENTRY_CRASH_MAX_PATH bytes (4096 on Linux, 260 on Windows)
- Passes options->handler_path->path directly to the daemon start
  function instead of storing it in shared memory first
- Updates tests to reflect the simplified behavior

Unlike ca_certs, proxy, and user_agent (which the daemon reads from
shared memory in init_daemon), handler_path is now passed directly
where it's actually needed.

Applied via @cursor push command
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.

2 participants