Skip to content

Commit cd62eb6

Browse files
committed
WIP: transfer feedback envelope ownership
1 parent 2b7b2a8 commit cd62eb6

File tree

11 files changed

+142
-68
lines changed

11 files changed

+142
-68
lines changed

include/sentry.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -698,6 +698,15 @@ SENTRY_API int sentry_envelope_write_to_file(
698698
SENTRY_API int sentry_envelope_write_to_file_n(
699699
const sentry_envelope_t *envelope, const char *path, size_t path_len);
700700

701+
/**
702+
* Reads an envelope from a file.
703+
*
704+
* `path` is assumed to be in platform-specific filesystem path encoding.
705+
*/
706+
SENTRY_API sentry_envelope_t *sentry_envelope_read_from_file(const char *path);
707+
SENTRY_API sentry_envelope_t *sentry_envelope_read_from_file_n(
708+
const char *path, size_t path_len);
709+
701710
/**
702711
* Submits an envelope, first checking for consent.
703712
*/

src/backends/sentry_backend_breakpad.cpp

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,6 @@ breakpad_backend_callback(const google_breakpad::MinidumpDescriptor &descriptor,
143143
}
144144

145145
if (should_handle) {
146-
sentry_value_incref(event);
147146
sentry_envelope_t *envelope = sentry__prepare_event(
148147
options, event, nullptr, !options->on_crash_func, NULL);
149148
sentry_session_t *session = sentry__end_current_session_with_status(
@@ -177,27 +176,30 @@ breakpad_backend_callback(const google_breakpad::MinidumpDescriptor &descriptor,
177176
sentry__attachment_free(screenshot);
178177
}
179178

180-
// capture the envelope with the disk transport
181-
sentry_transport_t *disk_transport
182-
= sentry_new_disk_transport(options->run);
183-
sentry__capture_envelope(disk_transport, envelope);
184-
sentry__transport_dump_queue(disk_transport, options->run);
185-
sentry_transport_free(disk_transport);
179+
if (options->feedback_handler_path) {
180+
sentry__launch_feedback_handler(envelope);
181+
} else {
182+
// capture the envelope with the disk transport
183+
sentry_transport_t *disk_transport
184+
= sentry_new_disk_transport(options->run);
185+
sentry__capture_envelope(disk_transport, envelope);
186+
sentry__transport_dump_queue(disk_transport, options->run);
187+
sentry_transport_free(disk_transport);
188+
}
186189

187190
// now that the envelope was written, we can remove the temporary
188191
// minidump file
189192
sentry__path_remove(dump_path);
190193
sentry__path_free(dump_path);
191194
} else {
192195
SENTRY_DEBUG("event was discarded by the `on_crash` hook");
196+
sentry_value_decref(event);
193197
}
194198

195199
// after capturing the crash event, try to dump all the in-flight
196200
// data of the previous transports
197201
sentry__transport_dump_queue(options->transport, options->run);
198-
// and launch the feedback handler
199-
sentry__launch_feedback_handler(event);
200-
sentry_value_decref(event);
202+
// and restore the old transport
201203
}
202204
SENTRY_INFO("crash has been captured");
203205

src/backends/sentry_backend_inproc.c

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -589,7 +589,6 @@ handle_ucontext(const sentry_ucontext_t *uctx)
589589
}
590590

591591
if (should_handle) {
592-
sentry_value_incref(event);
593592
sentry_envelope_t *envelope = sentry__prepare_event(
594593
options, event, NULL, !options->on_crash_func, NULL);
595594
// TODO(tracing): Revisit when investigating transaction flushing
@@ -609,21 +608,23 @@ handle_ucontext(const sentry_ucontext_t *uctx)
609608
sentry__attachment_free(screenshot);
610609
}
611610

612-
// capture the envelope with the disk transport
613-
sentry_transport_t *disk_transport
614-
= sentry_new_disk_transport(options->run);
615-
sentry__capture_envelope(disk_transport, envelope);
616-
sentry__transport_dump_queue(disk_transport, options->run);
617-
sentry_transport_free(disk_transport);
611+
if (options->feedback_handler_path) {
612+
sentry__launch_feedback_handler(envelope);
613+
} else {
614+
// capture the envelope with the disk transport
615+
sentry_transport_t *disk_transport
616+
= sentry_new_disk_transport(options->run);
617+
sentry__capture_envelope(disk_transport, envelope);
618+
sentry__transport_dump_queue(disk_transport, options->run);
619+
sentry_transport_free(disk_transport);
620+
}
618621
} else {
619622
SENTRY_DEBUG("event was discarded by the `on_crash` hook");
623+
sentry_value_decref(event);
620624
}
621625

622626
// after capturing the crash event, dump all the envelopes to disk
623627
sentry__transport_dump_queue(options->transport, options->run);
624-
// and launch the feedback handler
625-
sentry__launch_feedback_handler(event);
626-
sentry_value_decref(event);
627628
}
628629

629630
SENTRY_INFO("crash has been captured");

src/sentry_core.c

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "sentry_transport.h"
2323
#include "sentry_uuid.h"
2424
#include "sentry_value.h"
25+
#include "transports/sentry_disk_transport.h"
2526

2627
#ifdef SENTRY_INTEGRATION_QT
2728
# include "integrations/sentry_integration_qt.h"
@@ -1446,24 +1447,33 @@ sentry_capture_feedback(sentry_value_t user_feedback)
14461447
}
14471448

14481449
void
1449-
sentry__launch_feedback_handler(sentry_value_t event)
1450+
sentry__launch_feedback_handler(sentry_envelope_t *envelope)
14501451
{
1451-
sentry_uuid_t event_id = sentry_uuid_nil();
1452-
sentry__ensure_event_id(event, &event_id);
1452+
// sentry_uuid_t event_id = sentry_uuid_nil();
1453+
// sentry__ensure_event_id(event, &event_id);
14531454

14541455
SENTRY_WITH_OPTIONS (options) {
14551456
if (!options->feedback_handler_path) {
14561457
return;
14571458
}
14581459

1459-
sentry_path_t *feedback_path
1460-
= sentry__run_write_feedback(options->run, &event_id);
1461-
if (!feedback_path) {
1462-
return;
1460+
// capture the envelope with the disk transport
1461+
sentry_transport_t *disk_transport
1462+
= sentry_new_feedback_transport(options->run);
1463+
sentry__capture_envelope(disk_transport, envelope);
1464+
sentry__transport_dump_queue(disk_transport, options->run);
1465+
sentry_transport_free(disk_transport);
1466+
1467+
sentry_uuid_t event_id = sentry__envelope_get_event_id(envelope);
1468+
char *envelope_filename
1469+
= sentry__uuid_as_filename(&event_id, ".envelope");
1470+
1471+
sentry_path_t *feedback_path = sentry__path_join_str(
1472+
options->run->feedback_path, envelope_filename);
1473+
if (feedback_path) {
1474+
sentry__process_spawn(
1475+
options->feedback_handler_path, feedback_path->path, NULL);
14631476
}
1464-
1465-
sentry__process_spawn(
1466-
options->feedback_handler_path, feedback_path->path, NULL);
14671477
sentry__path_free(feedback_path);
14681478
}
14691479
}

src/sentry_core.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ void sentry__options_unlock(void);
122122

123123
void sentry__set_propagation_context(const char *key, sentry_value_t value);
124124

125-
void sentry__launch_feedback_handler(sentry_value_t event);
125+
void sentry__launch_feedback_handler(sentry_envelope_t *envelope);
126126

127127
#define SENTRY_WITH_OPTIONS(Options) \
128128
for (const sentry_options_t *Options = sentry__options_getref(); Options; \

src/sentry_database.c

Lines changed: 13 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -126,44 +126,33 @@ sentry__run_write_envelope(
126126

127127
sentry_path_t *
128128
sentry__run_write_feedback(
129-
const sentry_run_t *run, const sentry_uuid_t *event_id)
129+
const sentry_run_t *run, const sentry_envelope_t *envelope)
130130
{
131131
if (sentry__path_create_dir_all(run->feedback_path) != 0) {
132132
SENTRY_ERRORF(
133133
"mkdir failed: \"%" SENTRY_PATH_PRI "\"", run->feedback_path->path);
134134
return NULL;
135135
}
136136

137-
char *filename = sentry__uuid_as_filename(event_id, ".envelope");
138-
sentry_path_t *source_path = sentry__path_join_str(run->run_path, filename);
139-
140-
size_t buf_len = 0;
141-
char *buf = sentry__path_read_to_buffer(source_path, &buf_len);
142-
if (!buf || buf_len == 0) {
143-
SENTRY_ERRORF("failed to read envelope: \"%" SENTRY_PATH_PRI "\"",
144-
source_path->path);
145-
sentry_free(filename);
146-
sentry__path_free(source_path);
147-
sentry_free(buf);
137+
sentry_uuid_t event_id = sentry__envelope_get_event_id(envelope);
138+
char *envelope_filename = sentry__uuid_as_filename(&event_id, ".envelope");
139+
140+
sentry_path_t *output_path
141+
= sentry__path_join_str(run->feedback_path, envelope_filename);
142+
sentry_free(envelope_filename);
143+
if (!output_path) {
148144
return NULL;
149145
}
150146

151-
sentry_path_t *target_path
152-
= sentry__path_join_str(run->feedback_path, filename);
153-
int rv = sentry__path_write_buffer(target_path, buf, buf_len);
154-
155-
sentry_free(filename);
156-
sentry__path_free(source_path);
157-
sentry_free(buf);
147+
int rv = sentry_envelope_write_to_path(envelope, output_path);
148+
sentry__path_free(output_path);
158149

159150
if (rv) {
160-
SENTRY_ERRORF("failed to write feedback: \"%" SENTRY_PATH_PRI "\"",
161-
target_path->path);
162-
sentry__path_free(target_path);
163-
return NULL;
151+
SENTRY_WARN("writing envelope to file failed");
164152
}
165153

166-
return target_path;
154+
// the `write_to_path` returns > 0 on failure, but we would like a real bool
155+
return !rv ? output_path : NULL;
167156
}
168157

169158
bool

src/sentry_database.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,12 @@ bool sentry__run_write_envelope(
4343
const sentry_run_t *run, const sentry_envelope_t *envelope);
4444

4545
/**
46-
* This will copy the specified event's envelope from:
47-
* `<database>/<uuid>.run/<event-uuid>.envelope` to:
48-
* `<database>/feedback/<event-uuid>.envelope`.
46+
* This will serialize and write the given envelope to disk into a file named
47+
* like so:
48+
* `<database>/feedback/<event-uuid>.envelope`
4949
*/
5050
sentry_path_t *sentry__run_write_feedback(
51-
const sentry_run_t *run, const sentry_uuid_t *event_id);
51+
const sentry_run_t *run, const sentry_envelope_t *envelope);
5252

5353
/**
5454
* This will serialize and write the given session to disk into a file named:

src/sentry_envelope.c

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,8 +189,21 @@ sentry_uuid_t
189189
sentry__envelope_get_event_id(const sentry_envelope_t *envelope)
190190
{
191191
if (envelope->is_raw) {
192-
return sentry_uuid_nil();
193-
}
192+
const char *payload = envelope->contents.raw.payload;
193+
size_t payload_len = envelope->contents.raw.payload_len;
194+
if (!payload || payload_len == 0) {
195+
return sentry_uuid_nil();
196+
}
197+
198+
const char *newline = memchr(payload, '\n', payload_len);
199+
size_t headers_len
200+
= newline ? (size_t)(newline - payload) : payload_len;
201+
sentry_value_t headers = sentry__value_from_json(payload, headers_len);
202+
sentry_uuid_t event_id = sentry_uuid_from_string(sentry_value_as_string(
203+
sentry_value_get_by_key(headers, "event_id")));
204+
sentry_value_decref(headers);
205+
return event_id;
206+
};
194207
return sentry_uuid_from_string(sentry_value_as_string(
195208
sentry_value_get_by_key(envelope->contents.items.headers, "event_id")));
196209
}
@@ -726,6 +739,24 @@ sentry_envelope_write_to_file(
726739
return sentry_envelope_write_to_file_n(envelope, path, strlen(path));
727740
}
728741

742+
sentry_envelope_t *
743+
sentry_envelope_read_from_file(const char *path)
744+
{
745+
sentry_path_t *path_obj = sentry__path_from_str(path);
746+
sentry_envelope_t *envelope = sentry__envelope_from_path(path_obj);
747+
sentry__path_free(path_obj);
748+
return envelope;
749+
}
750+
751+
sentry_envelope_t *
752+
sentry_envelope_read_from_file_n(const char *path, size_t path_len)
753+
{
754+
sentry_path_t *path_obj = sentry__path_from_str_n(path, path_len);
755+
sentry_envelope_t *envelope = sentry__envelope_from_path(path_obj);
756+
sentry__path_free(path_obj);
757+
return envelope;
758+
}
759+
729760
#ifdef SENTRY_UNITTEST
730761
size_t
731762
sentry__envelope_get_item_count(const sentry_envelope_t *envelope)

src/transports/sentry_disk_transport.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,24 @@ sentry_new_disk_transport(const sentry_run_t *run)
2626
sentry_transport_set_state(transport, (void *)run);
2727
return transport;
2828
}
29+
30+
static void
31+
send_feedback_disk_transport(sentry_envelope_t *envelope, void *state)
32+
{
33+
const sentry_run_t *run = state;
34+
35+
sentry__run_write_feedback(run, envelope);
36+
sentry_envelope_free(envelope);
37+
}
38+
39+
sentry_transport_t *
40+
sentry_new_feedback_transport(const sentry_run_t *run)
41+
{
42+
sentry_transport_t *transport
43+
= sentry_transport_new(send_feedback_disk_transport);
44+
if (!transport) {
45+
return NULL;
46+
}
47+
sentry_transport_set_state(transport, (void *)run);
48+
return transport;
49+
}

src/transports/sentry_disk_transport.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,11 @@
1111
*/
1212
sentry_transport_t *sentry_new_disk_transport(const sentry_run_t *run);
1313

14+
/**
15+
* This creates a new transport that serializes envelopes to disk in the given
16+
* `feedback` directory.
17+
* See `sentry__run_write_feedback`.
18+
*/
19+
sentry_transport_t *sentry_new_feedback_transport(const sentry_run_t *run);
20+
1421
#endif

0 commit comments

Comments
 (0)