diff --git a/CHANGELOG.md b/CHANGELOG.md index de36b19f2..546ad1136 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ - Fix event ownership (potential double-decref) in sentry_capture_minidump. ([#1669](https://github.com/getsentry/sentry-native/pull/1669)) - Guard against internal stringbuilder append and reserve size overflows. ([#1672](https://github.com/getsentry/sentry-native/pull/1672)) +- Preserve attachments added during crash handling ([#1687](https://github.com/getsentry/sentry-native/pull/1687)) ## 0.13.8 diff --git a/src/backends/sentry_backend_native.c b/src/backends/sentry_backend_native.c index 9d43d6c3a..78d436784 100644 --- a/src/backends/sentry_backend_native.c +++ b/src/backends/sentry_backend_native.c @@ -584,12 +584,71 @@ native_backend_free(sentry_backend_t *backend) sentry_free(state); } +// Writes the scope's attachment list to /__sentry-attachments so the +// crash daemon can locate and append them to the crash envelope. +static void +native_backend_write_attachments(const sentry_path_t *event_path) +{ + if (!event_path) { + return; + } + SENTRY_WITH_SCOPE (scope) { + if (!scope->attachments) { + continue; + } + sentry_path_t *run_path = sentry__path_dir(event_path); + if (!run_path) { + continue; + } + sentry_path_t *attach_list_path + = sentry__path_join_str(run_path, "__sentry-attachments"); + if (attach_list_path) { + sentry_value_t attach_list = sentry_value_new_list(); + for (sentry_attachment_t *it = scope->attachments; it; + it = it->next) { + if (!it->path) { + continue; + } + sentry_value_t attach_info = sentry_value_new_object(); + sentry_value_set_by_key(attach_info, "path", + sentry_value_new_string(it->path->path)); + const char *filename = sentry__path_filename( + it->filename ? it->filename : it->path); + sentry_value_set_by_key( + attach_info, "filename", sentry_value_new_string(filename)); + if (it->content_type) { + sentry_value_set_by_key(attach_info, "content_type", + sentry_value_new_string(it->content_type)); + } + sentry_value_append(attach_list, attach_info); + } + char *attach_json = sentry_value_to_json(attach_list); + sentry_value_decref(attach_list); + if (attach_json) { + sentry__path_write_buffer( + attach_list_path, attach_json, strlen(attach_json)); + sentry_free(attach_json); + } + sentry__path_free(attach_list_path); + } + sentry__path_free(run_path); + } +} + static void native_backend_flush_scope( sentry_backend_t *backend, const sentry_options_t *UNUSED(options)) { native_backend_state_t *state = (native_backend_state_t *)backend->data; - if (!state || !state->event_path || sentry__atomic_fetch(&state->crashed)) { + if (!state || !state->event_path) { + return; + } + + // Manifest writes must continue post-crash so attachments registered + // from on_crash/before_send reach the daemon + native_backend_write_attachments(state->event_path); + + if (sentry__atomic_fetch(&state->crashed)) { return; } @@ -659,50 +718,6 @@ native_backend_flush_scope( sentry__path_write_buffer(state->event_path, json_str, json_len); sentry_free(json_str); } - - // Write attachment metadata (paths and filenames) so crash daemon can find - // them - SENTRY_WITH_SCOPE (scope) { - if (scope->attachments) { - sentry_path_t *run_path = sentry__path_dir(state->event_path); - if (run_path) { - sentry_path_t *attach_list_path - = sentry__path_join_str(run_path, "__sentry-attachments"); - if (attach_list_path) { - // Write attachment list as JSON array - sentry_value_t attach_list = sentry_value_new_list(); - for (sentry_attachment_t *it = scope->attachments; it; - it = it->next) { - if (it->path) { - sentry_value_t attach_info - = sentry_value_new_object(); - sentry_value_set_by_key(attach_info, "path", - sentry_value_new_string(it->path->path)); - const char *filename = sentry__path_filename( - it->filename ? it->filename : it->path); - sentry_value_set_by_key(attach_info, "filename", - sentry_value_new_string(filename)); - if (it->content_type) { - sentry_value_set_by_key(attach_info, - "content_type", - sentry_value_new_string(it->content_type)); - } - sentry_value_append(attach_list, attach_info); - } - } - char *attach_json = sentry_value_to_json(attach_list); - sentry_value_decref(attach_list); - if (attach_json) { - sentry__path_write_buffer( - attach_list_path, attach_json, strlen(attach_json)); - sentry_free(attach_json); - } - sentry__path_free(attach_list_path); - } - sentry__path_free(run_path); - } - } - } } static void