Skip to content

Commit 48c69e8

Browse files
committed
Merge remote-tracking branch 'upstream/master' into jpnurmi/feat/native-offline-caching
2 parents c06ecfb + 231d9a6 commit 48c69e8

8 files changed

Lines changed: 134 additions & 99 deletions

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
**Fixes**:
1010

1111
- Fix `cache_keep` to only cache envelopes when HTTP send fails, instead of unconditionally on restart. ([#1585](https://github.com/getsentry/sentry-native/pull/1585))
12+
- Fix external crash reporter to work with the new experimental `native` backend. ([#1589](https://github.com/getsentry/sentry-native/pull/1589))
1213

1314
## 0.13.3
1415

src/backends/native/sentry_crash_daemon.c

Lines changed: 70 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2032,10 +2032,13 @@ write_envelope_with_native_stacktrace(const sentry_options_t *options,
20322032

20332033
// Serialize event to JSON
20342034
char *event_json = sentry_value_to_json(event);
2035+
char *event_id = sentry__string_clone(
2036+
sentry_value_as_string(sentry_value_get_by_key(event, "event_id")));
20352037
sentry_value_decref(event);
20362038

20372039
if (!event_json) {
20382040
SENTRY_WARN("Failed to serialize native crash event to JSON");
2041+
sentry_free(event_id);
20392042
return false;
20402043
}
20412044

@@ -2054,6 +2057,7 @@ write_envelope_with_native_stacktrace(const sentry_options_t *options,
20542057
if (fd < 0) {
20552058
SENTRY_WARN("Failed to open envelope file for writing");
20562059
sentry_free(event_json);
2060+
sentry_free(event_id);
20572061
return false;
20582062
}
20592063

@@ -2062,12 +2066,19 @@ write_envelope_with_native_stacktrace(const sentry_options_t *options,
20622066
= options && options->dsn ? sentry_options_get_dsn(options) : NULL;
20632067
char header_buf[SENTRY_CRASH_ENVELOPE_HEADER_SIZE];
20642068
int header_len;
2065-
if (dsn) {
2069+
if (dsn && event_id && event_id[0] != '\0') {
2070+
header_len = snprintf(header_buf, sizeof(header_buf),
2071+
"{\"dsn\":\"%s\",\"event_id\":\"%s\"}\n", dsn, event_id);
2072+
} else if (dsn) {
20662073
header_len = snprintf(
20672074
header_buf, sizeof(header_buf), "{\"dsn\":\"%s\"}\n", dsn);
2075+
} else if (event_id && event_id[0] != '\0') {
2076+
header_len = snprintf(header_buf, sizeof(header_buf),
2077+
"{\"event_id\":\"%s\"}\n", event_id);
20682078
} else {
20692079
header_len = snprintf(header_buf, sizeof(header_buf), "{}\n");
20702080
}
2081+
sentry_free(event_id);
20712082
if (header_len > 0 && header_len < (int)sizeof(header_buf)) {
20722083
#if defined(SENTRY_PLATFORM_UNIX)
20732084
if (write(fd, header_buf, header_len) != header_len) {
@@ -2238,6 +2249,23 @@ write_envelope_with_minidump(const sentry_options_t *options,
22382249
const char *envelope_path, const char *event_msgpack_path,
22392250
const char *minidump_path, sentry_path_t *run_folder)
22402251
{
2252+
// Read event JSON data
2253+
size_t event_size = 0;
2254+
char *event_json = NULL;
2255+
char *event_id = NULL;
2256+
sentry_path_t *ev_path = sentry__path_from_str(event_msgpack_path);
2257+
if (ev_path) {
2258+
event_json = sentry__path_read_to_buffer(ev_path, &event_size);
2259+
sentry__path_free(ev_path);
2260+
if (event_json && event_size > 0) {
2261+
sentry_value_t event
2262+
= sentry__value_from_json(event_json, event_size);
2263+
event_id = sentry__string_clone(sentry_value_as_string(
2264+
sentry_value_get_by_key(event, "event_id")));
2265+
sentry_value_decref(event);
2266+
}
2267+
}
2268+
22412269
// Open envelope file for writing
22422270
#if defined(SENTRY_PLATFORM_UNIX)
22432271
int fd = open(envelope_path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
@@ -2251,20 +2279,29 @@ write_envelope_with_minidump(const sentry_options_t *options,
22512279
#endif
22522280
if (fd < 0) {
22532281
SENTRY_WARN("Failed to open envelope file for writing");
2282+
sentry_free(event_json);
2283+
sentry_free(event_id);
22542284
return false;
22552285
}
22562286

2257-
// Write envelope headers (just DSN if available)
2287+
// Write envelope headers (just DSN and event ID if available)
22582288
const char *dsn
22592289
= options && options->dsn ? sentry_options_get_dsn(options) : NULL;
22602290
char header_buf[SENTRY_CRASH_ENVELOPE_HEADER_SIZE];
22612291
int header_len;
2262-
if (dsn) {
2292+
if (dsn && event_id && event_id[0] != '\0') {
2293+
header_len = snprintf(header_buf, sizeof(header_buf),
2294+
"{\"dsn\":\"%s\",\"event_id\":\"%s\"}\n", dsn, event_id);
2295+
} else if (dsn) {
22632296
header_len = snprintf(
22642297
header_buf, sizeof(header_buf), "{\"dsn\":\"%s\"}\n", dsn);
2298+
} else if (event_id && event_id[0] != '\0') {
2299+
header_len = snprintf(header_buf, sizeof(header_buf),
2300+
"{\"event_id\":\"%s\"}\n", event_id);
22652301
} else {
22662302
header_len = snprintf(header_buf, sizeof(header_buf), "{}\n");
22672303
}
2304+
sentry_free(event_id);
22682305
if (header_len > 0 && header_len < (int)sizeof(header_buf)) {
22692306
#if defined(SENTRY_PLATFORM_UNIX)
22702307
if (write(fd, header_buf, header_len) != header_len) {
@@ -2275,39 +2312,30 @@ write_envelope_with_minidump(const sentry_options_t *options,
22752312
#endif
22762313
}
22772314

2278-
// Read event JSON data
2279-
sentry_path_t *ev_path = sentry__path_from_str(event_msgpack_path);
2280-
if (ev_path) {
2281-
size_t event_size = 0;
2282-
char *event_json = sentry__path_read_to_buffer(ev_path, &event_size);
2283-
sentry__path_free(ev_path);
2284-
2285-
if (event_json && event_size > 0) {
2286-
// Write event item header
2287-
char event_header[SENTRY_CRASH_ITEM_HEADER_SIZE];
2288-
int ev_header_len = snprintf(event_header, sizeof(event_header),
2289-
"{\"type\":\"event\",\"length\":%zu}\n", event_size);
2290-
if (ev_header_len > 0
2291-
&& ev_header_len < (int)sizeof(event_header)) {
2315+
// Write event item
2316+
if (event_json && event_size > 0) {
2317+
char event_header[SENTRY_CRASH_ITEM_HEADER_SIZE];
2318+
int ev_header_len = snprintf(event_header, sizeof(event_header),
2319+
"{\"type\":\"event\",\"length\":%zu}\n", event_size);
2320+
if (ev_header_len > 0 && ev_header_len < (int)sizeof(event_header)) {
22922321
#if defined(SENTRY_PLATFORM_UNIX)
2293-
if (write(fd, event_header, ev_header_len) != ev_header_len) {
2294-
SENTRY_WARN("Failed to write event header to envelope");
2295-
}
2296-
if (write(fd, event_json, event_size) != (ssize_t)event_size) {
2297-
SENTRY_WARN("Failed to write event data to envelope");
2298-
}
2299-
if (write(fd, "\n", 1) != 1) {
2300-
SENTRY_WARN("Failed to write event newline to envelope");
2301-
}
2322+
if (write(fd, event_header, ev_header_len) != ev_header_len) {
2323+
SENTRY_WARN("Failed to write event header to envelope");
2324+
}
2325+
if (write(fd, event_json, event_size) != (ssize_t)event_size) {
2326+
SENTRY_WARN("Failed to write event data to envelope");
2327+
}
2328+
if (write(fd, "\n", 1) != 1) {
2329+
SENTRY_WARN("Failed to write event newline to envelope");
2330+
}
23022331
#elif defined(SENTRY_PLATFORM_WINDOWS)
2303-
_write(fd, event_header, (unsigned int)ev_header_len);
2304-
_write(fd, event_json, (unsigned int)event_size);
2305-
_write(fd, "\n", 1);
2332+
_write(fd, event_header, (unsigned int)ev_header_len);
2333+
_write(fd, event_json, (unsigned int)event_size);
2334+
_write(fd, "\n", 1);
23062335
#endif
2307-
}
2308-
sentry_free(event_json);
23092336
}
23102337
}
2338+
sentry_free(event_json);
23112339

23122340
// Add minidump as attachment
23132341
#if defined(SENTRY_PLATFORM_UNIX)
@@ -2712,14 +2740,17 @@ sentry__process_crash(const sentry_options_t *options, sentry_crash_ipc_t *ipc)
27122740

27132741
SENTRY_DEBUG("Envelope loaded, sending via transport");
27142742

2715-
// Send directly via transport
2716-
if (options && options->transport) {
2717-
SENTRY_DEBUG("Calling transport send_envelope");
2718-
sentry__transport_send_envelope(options->transport, envelope);
2719-
SENTRY_DEBUG("Crash envelope sent to transport (queued)");
2720-
} else {
2721-
SENTRY_WARN("No transport available for sending envelope");
2722-
sentry_envelope_free(envelope);
2743+
// Send directly via transport, or to external crash reporter
2744+
if (!sentry__launch_external_crash_reporter(options, envelope)) {
2745+
// Send directly via transport
2746+
if (options && options->transport) {
2747+
SENTRY_DEBUG("Calling transport send_envelope");
2748+
sentry__transport_send_envelope(options->transport, envelope);
2749+
SENTRY_DEBUG("Crash envelope sent to transport (queued)");
2750+
} else {
2751+
SENTRY_WARN("No transport available for sending envelope");
2752+
sentry_envelope_free(envelope);
2753+
}
27232754
}
27242755

27252756
// Clean up temporary envelope file (keep minidump for

src/backends/sentry_backend_breakpad.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ breakpad_backend_callback(const google_breakpad::MinidumpDescriptor &descriptor,
190190
sentry__attachment_free(screenshot);
191191
}
192192

193-
if (!sentry__launch_external_crash_reporter(envelope)) {
193+
if (!sentry__launch_external_crash_reporter(options, envelope)) {
194194
// capture the envelope with the disk transport
195195
sentry_transport_t *disk_transport
196196
= sentry_new_disk_transport(options->run);

src/backends/sentry_backend_inproc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1190,7 +1190,7 @@ process_ucontext_deferred(const sentry_ucontext_t *uctx,
11901190
sentry__attachment_free(screenshot);
11911191
}
11921192

1193-
if (!sentry__launch_external_crash_reporter(envelope)) {
1193+
if (!sentry__launch_external_crash_reporter(options, envelope)) {
11941194
// capture the envelope with the disk transport
11951195
sentry_transport_t *disk_transport
11961196
= sentry_new_disk_transport(options->run);

src/backends/sentry_backend_native.c

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -542,7 +542,7 @@ native_backend_free(sentry_backend_t *backend)
542542

543543
static void
544544
native_backend_flush_scope(
545-
sentry_backend_t *backend, const sentry_options_t *options)
545+
sentry_backend_t *backend, const sentry_options_t *UNUSED(options))
546546
{
547547
native_backend_state_t *state = (native_backend_state_t *)backend->data;
548548
if (!state || !state->event_path) {
@@ -659,16 +659,6 @@ native_backend_flush_scope(
659659
}
660660
}
661661
}
662-
663-
// Flush external crash report envelope if configured
664-
if (options->external_crash_reporter && state->envelope_path) {
665-
sentry_envelope_t *envelope = sentry__envelope_new();
666-
if (envelope && options->session) {
667-
sentry__envelope_add_session(envelope, options->session);
668-
sentry__run_write_external(options->run, envelope);
669-
}
670-
sentry_envelope_free(envelope);
671-
}
672662
}
673663

674664
static void

src/sentry_core.c

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1662,44 +1662,44 @@ sentry_capture_feedback_with_hint(
16621662
}
16631663

16641664
bool
1665-
sentry__launch_external_crash_reporter(sentry_envelope_t *envelope)
1665+
sentry__launch_external_crash_reporter(
1666+
const sentry_options_t *options, sentry_envelope_t *envelope)
16661667
{
1667-
SENTRY_WITH_OPTIONS (options) {
1668-
if (!options->external_crash_reporter) {
1669-
return false;
1670-
}
1671-
1672-
sentry_uuid_t event_id = sentry__envelope_get_event_id(envelope);
1673-
char *envelope_filename
1674-
= sentry__uuid_as_filename(&event_id, ".envelope");
1675-
if (!envelope_filename) {
1676-
return false;
1677-
}
1668+
if (!options || !options->run || !options->external_crash_reporter
1669+
|| !options->external_crash_reporter->path
1670+
|| options->external_crash_reporter->path[0] == '\0') {
1671+
return false;
1672+
}
16781673

1679-
sentry_path_t *report_path = sentry__path_join_str(
1680-
options->run->external_path, envelope_filename);
1681-
if (!report_path) {
1682-
sentry_free(envelope_filename);
1683-
return false;
1684-
}
1674+
sentry_uuid_t event_id = sentry__envelope_get_event_id(envelope);
1675+
char *envelope_filename = sentry__uuid_as_filename(&event_id, ".envelope");
1676+
if (!envelope_filename) {
1677+
return false;
1678+
}
16851679

1686-
// capture the envelope with the disk transport
1687-
sentry_transport_t *disk_transport
1688-
= sentry_new_external_disk_transport(options->run);
1689-
if (!disk_transport) {
1690-
sentry__path_free(report_path);
1691-
sentry_free(envelope_filename);
1692-
return false;
1693-
}
1694-
sentry__capture_envelope(disk_transport, envelope);
1695-
sentry__transport_dump_queue(disk_transport, options->run);
1696-
sentry_transport_free(disk_transport);
1680+
sentry_path_t *report_path
1681+
= sentry__path_join_str(options->run->external_path, envelope_filename);
1682+
if (!report_path) {
1683+
sentry_free(envelope_filename);
1684+
return false;
1685+
}
16971686

1698-
sentry__process_spawn(
1699-
options->external_crash_reporter, report_path->path, NULL);
1687+
// capture the envelope with the disk transport
1688+
sentry_transport_t *disk_transport
1689+
= sentry_new_external_disk_transport(options->run);
1690+
if (!disk_transport) {
17001691
sentry__path_free(report_path);
17011692
sentry_free(envelope_filename);
1693+
return false;
17021694
}
1695+
sentry__transport_send_envelope(disk_transport, envelope);
1696+
sentry__transport_dump_queue(disk_transport, options->run);
1697+
sentry_transport_free(disk_transport);
1698+
1699+
sentry__process_spawn(
1700+
options->external_crash_reporter, report_path->path, NULL);
1701+
sentry__path_free(report_path);
1702+
sentry_free(envelope_filename);
17031703
return true;
17041704
}
17051705

src/sentry_core.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,8 @@ void sentry__set_propagation_context(const char *key, sentry_value_t value);
128128
void sentry__apply_attributes(
129129
sentry_value_t telemetry, sentry_value_t attributes);
130130

131-
bool sentry__launch_external_crash_reporter(sentry_envelope_t *envelope);
131+
bool sentry__launch_external_crash_reporter(
132+
const sentry_options_t *options, sentry_envelope_t *envelope);
132133

133134
#define SENTRY_WITH_OPTIONS(Options) \
134135
for (const sentry_options_t *Options = sentry__options_getref(); Options; \

tests/test_integration_native.py

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,18 @@
1212
import pytest
1313

1414
from . import (
15+
is_feedback_envelope,
1516
make_dsn,
1617
run,
1718
Envelope,
19+
split_log_request_cond,
1820
)
1921
from .assertions import (
22+
assert_breadcrumb,
2023
assert_meta,
2124
assert_session,
2225
wait_for_file,
26+
assert_user_feedback,
2327
)
2428
from .conditions import has_native, is_kcov, is_asan
2529

@@ -473,26 +477,34 @@ def test_native_external_crash_reporter(cmake, httpserver):
473477
)
474478

475479
env = dict(os.environ, SENTRY_DSN=make_dsn(httpserver))
476-
httpserver.expect_request("/api/123456/envelope/").respond_with_data("OK")
480+
httpserver.expect_oneshot_request("/api/123456/envelope/").respond_with_data("OK")
481+
httpserver.expect_oneshot_request("/api/123456/envelope/").respond_with_data("OK")
477482

478483
# Crash and use external reporter
479-
run_crash(
480-
tmp_path,
481-
"sentry_example",
482-
["log", "crash-reporter", "crash"],
483-
env=env,
484-
)
484+
with httpserver.wait(timeout=10) as waiting:
485+
run_crash(
486+
tmp_path,
487+
"sentry_example",
488+
["log", "crash-reporter", "crash"],
489+
env=env,
490+
)
491+
assert waiting.result
485492

486-
# Give time for external reporter to run
487-
time.sleep(2)
493+
# Should have sent crash report and feedback via external reporter
494+
assert len(httpserver.log) == 2
495+
feedback_request, crash_request = split_log_request_cond(
496+
httpserver.log, is_feedback_envelope
497+
)
498+
feedback = feedback_request.get_data()
499+
crash = crash_request.get_data()
488500

489-
# Should have sent crash report via external reporter
490-
assert len(httpserver.log) >= 1
501+
# Verify it's a minidump crash report and user feedback
502+
envelope = Envelope.deserialize(crash)
503+
assert_meta(envelope)
504+
assert_breadcrumb(envelope)
491505

492-
# Verify it's a minidump crash report
493-
envelope = Envelope.deserialize(httpserver.log[0][0].get_data())
494-
event = envelope.get_event()
495-
assert event is not None
506+
envelope = Envelope.deserialize(feedback)
507+
assert_user_feedback(envelope)
496508

497509

498510
def test_crash_mode_minidump_only(cmake, httpserver):

0 commit comments

Comments
 (0)