diff --git a/CHANGELOG.md b/CHANGELOG.md index ec31d4c5c4..c43caaf8da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ - Report enabled Qt and WER integrations in event SDK metadata (`sdk.integrations`) alongside the configured crash backend. ([#1969](https://github.com/ getsentry/sentry-native/pull/1969)) +**Fixes**: + +- Native/Linux: improve startup time by avoiding zeroing a large shmem module array during crash context initialization. ([#1966](https://github.com/getsentry/sentry-native/pull/1966)) + ## 0.16.2 **Features**: diff --git a/src/backends/native/sentry_crash_context.h b/src/backends/native/sentry_crash_context.h index be172a97b5..20681b812b 100644 --- a/src/backends/native/sentry_crash_context.h +++ b/src/backends/native/sentry_crash_context.h @@ -9,9 +9,12 @@ #include "sentry.h" // For sentry_minidump_mode_t #include "sentry_boot.h" +#include "sentry_sync.h" #include +#include #include +#include #if defined(SENTRY_PLATFORM_UNIX) # include @@ -326,12 +329,35 @@ typedef struct { // Minidump output path (filled by daemon) char minidump_path[SENTRY_CRASH_MAX_PATH]; + uint32_t module_count; // Guards modules[] (uninitialized) + + // === UNINITIALIZED MEMORY BEGIN === + // Module information (captured in signal handler from dyld) - uint32_t module_count; sentry_module_info_t modules[SENTRY_CRASH_MAX_MODULES]; + // NOTE: Any new members added here remain uninitialized by + // sentry__crash_context_init(). + } sentry_crash_context_t; +static inline void +sentry__crash_context_init(sentry_crash_context_t *ctx) +{ + if (!ctx) { + return; + } + + // Zero until the large modules[] array, and leave the rest uninitialized: + // https://github.com/getsentry/sentry-native/issues/1852 + memset(ctx, 0, offsetof(sentry_crash_context_t, modules)); + + ctx->magic = SENTRY_CRASH_MAGIC; + ctx->version = SENTRY_CRASH_VERSION; + sentry__atomic_store(&ctx->state, SENTRY_CRASH_STATE_READY); + sentry__atomic_store(&ctx->sequence, 0); +} + // Shared memory size: calculated at compile-time based on actual struct size // Add 8KB padding for safety and future additions #define SENTRY_CRASH_SHM_SIZE (sizeof(sentry_crash_context_t) + (8 * 1024)) diff --git a/src/backends/native/sentry_crash_ipc.c b/src/backends/native/sentry_crash_ipc.c index c929a07d5c..deafe3ca51 100644 --- a/src/backends/native/sentry_crash_ipc.c +++ b/src/backends/native/sentry_crash_ipc.c @@ -152,11 +152,7 @@ sentry__crash_ipc_init_app(sem_t *init_sem) // Initialize shared memory only if newly created if (!shm_exists) { - memset(ipc->shmem, 0, SENTRY_CRASH_SHM_SIZE); - ipc->shmem->magic = SENTRY_CRASH_MAGIC; - ipc->shmem->version = SENTRY_CRASH_VERSION; - sentry__atomic_store(&ipc->shmem->state, SENTRY_CRASH_STATE_READY); - sentry__atomic_store(&ipc->shmem->sequence, 0); + sentry__crash_context_init(ipc->shmem); } // Release semaphore after initialization @@ -450,11 +446,7 @@ sentry__crash_ipc_init_app(sentry_mutex_t *init_mutex) } if (!shm_exists) { - memset(ipc->shmem, 0, SENTRY_CRASH_SHM_SIZE); - ipc->shmem->magic = SENTRY_CRASH_MAGIC; - ipc->shmem->version = SENTRY_CRASH_VERSION; - sentry__atomic_store(&ipc->shmem->state, SENTRY_CRASH_STATE_READY); - sentry__atomic_store(&ipc->shmem->sequence, 0); + sentry__crash_context_init(ipc->shmem); } if (ipc->init_mutex) { @@ -707,11 +699,7 @@ sentry__crash_ipc_init_app(HANDLE init_mutex) // Initialize shared memory only if newly created if (!shm_exists) { - memset(ipc->shmem, 0, SENTRY_CRASH_SHM_SIZE); - ipc->shmem->magic = SENTRY_CRASH_MAGIC; - ipc->shmem->version = SENTRY_CRASH_VERSION; - sentry__atomic_store(&ipc->shmem->state, SENTRY_CRASH_STATE_READY); - sentry__atomic_store(&ipc->shmem->sequence, 0); + sentry__crash_context_init(ipc->shmem); } // Release mutex after initialization diff --git a/tests/unit/test_native_backend.c b/tests/unit/test_native_backend.c index 8125f23206..0bf86275aa 100644 --- a/tests/unit/test_native_backend.c +++ b/tests/unit/test_native_backend.c @@ -387,6 +387,32 @@ SENTRY_TEST(crash_context_transport_fields) #endif } +SENTRY_TEST(crash_context_init) +{ +#ifdef SENTRY_BACKEND_NATIVE + sentry_crash_context_t *ctx = sentry_malloc(sizeof(*ctx)); + TEST_ASSERT(!!ctx); + memset(ctx, 0xA5, sizeof(*ctx)); + + sentry__crash_context_init(ctx); + + TEST_CHECK_INT_EQUAL(ctx->magic, SENTRY_CRASH_MAGIC); + TEST_CHECK_INT_EQUAL(ctx->version, SENTRY_CRASH_VERSION); + TEST_CHECK_INT_EQUAL(ctx->state, SENTRY_CRASH_STATE_READY); + TEST_CHECK_INT_EQUAL(ctx->sequence, 0); + TEST_CHECK_INT_EQUAL(ctx->module_count, 0); + + TEST_CHECK( + ((unsigned char *)ctx)[offsetof(sentry_crash_context_t, modules) - 1] + == 0); + TEST_CHECK(((unsigned char *)&ctx->modules[0])[0] == 0xA5); + + sentry_free(ctx); +#else + SKIP_TEST(); +#endif +} + /** * Test that options transport configuration is propagated to crash context * during native backend startup. This verifies the fix for the daemon diff --git a/tests/unit/tests.inc b/tests/unit/tests.inc index dbc372ead4..dbc00cae5c 100644 --- a/tests/unit/tests.inc +++ b/tests/unit/tests.inc @@ -107,6 +107,7 @@ XX(cond_wake_all) XX(continuation_no_baggage_uses_sdk_dsc) XX(count_sampled_events) XX(crash_context_handler_path_propagation) +XX(crash_context_init) XX(crash_context_null_options) XX(crash_context_options_propagation) XX(crash_context_transport_fields)