Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ IndentPPDirectives: AfterHash
ColumnLimit: 80
AlwaysBreakAfterDefinitionReturnType: All
PointerAlignment: Right
ForEachMacros: ['SENTRY_WITH_SCOPE', 'SENTRY_WITH_SCOPE_MUT', 'SENTRY_WITH_SCOPE_MUT_NO_FLUSH', 'SENTRY_WITH_OPTIONS', 'SENTRY_WITH_OPTIONS_MUT']
ForEachMacros: ['SENTRY_WITH_SCOPE', 'SENTRY_WITH_SCOPE_MUT', 'SENTRY_WITH_SCOPE_MUT_NO_FLUSH', 'SENTRY_WITH_OPTIONS', 'SENTRY_WITH_OPTIONS_MUT', 'SENTRY_SCOPE_READ_LOCK', 'SENTRY_SCOPE_WRITE_LOCK']
InsertNewlineAtEOF: True
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@

- Deprecate `sentry_clear_crashed_last_run()` because `sentry_init()` now consumes the marker automatically. ([#2023](https://github.com/getsentry/sentry-native/pull/2023))

**Fixes**:

- Reduce lock contention for multi-threaded log and metric capture by allowing concurrent reads of scope data. ([#2042](https://github.com/getsentry/sentry-native/pull/2042))

## 0.16.6

**Features**:
Expand Down
222 changes: 121 additions & 101 deletions src/backends/sentry_backend_crashpad.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ typedef struct {
std::atomic<bool> crashed;
std::atomic<bool> scope_flush;
sentry_uuid_t crash_event_id;
sentry_scope_observer_t *scope_observer;
} crashpad_state_t;

/**
Expand Down Expand Up @@ -800,6 +801,99 @@ process_completed_reports(
}
}

#if defined(SENTRY_PLATFORM_WINDOWS) || defined(SENTRY_PLATFORM_LINUX) \
|| defined(SENTRY_PLATFORM_MACOS)
static sentry_path_t *
make_attachment_path(const sentry_path_t *run_path, sentry_value_t attachment)
{
if (!sentry__attachment_get_bytes(attachment, nullptr)) {
return sentry__attachment_make_path(attachment);
}

sentry_uuid_t id = sentry__attachment_get_id(attachment);
const char *filename = sentry__attachment_get_filename(attachment);
if (!run_path || sentry_uuid_is_nil(&id)
|| sentry__string_empty(filename)) {
return nullptr;
}

char uuid[37];
sentry_uuid_as_string(&id, uuid);
sentry_path_t *dir = sentry__path_join_str(run_path, uuid);
sentry_path_t *path = dir ? sentry__path_join_str(dir, filename) : nullptr;
sentry_path_t *parent = path ? sentry__path_dir(path) : nullptr;
bool valid = parent && sentry__path_eq(parent, dir);
sentry__path_free(parent);
sentry__path_free(dir);
if (!valid) {
sentry__path_free(path);
return nullptr;
}
return path;
}

static void
add_attachment(void *state, sentry_value_t attachment)
{
auto *data = static_cast<crashpad_state_t *>(state);
if (!data || !data->client) {
return;
}

size_t bytes_len = 0;
const char *bytes = sentry__attachment_get_bytes(attachment, &bytes_len);
sentry_path_t *path = make_attachment_path(data->run_path, attachment);
if (!path) {
const char *filename = sentry__attachment_get_filename(attachment);
SENTRY_WARNF("failed to create path for crashpad attachment \"%s\"",
filename ? filename : "<unknown>");
return;
}

if (bytes) {
sentry_path_t *dir = sentry__path_dir(path);
int rv = dir ? sentry__path_create_dir_all(dir) : 1;
sentry__path_free(dir);
if (rv != 0 || sentry__path_write_buffer(path, bytes, bytes_len) != 0) {
SENTRY_WARNF(
"failed to write crashpad attachment \"%s\"", path->path);
sentry__path_remove(path);
sentry__path_free(path);
return;
}
}
data->client->AddAttachment(base::FilePath(SENTRY_PATH_PLATFORM_STR(path)));
sentry__path_free(path);
}

static void
remove_attachment(void *state, sentry_value_t attachment)
{
auto *data = static_cast<crashpad_state_t *>(state);
if (!data || !data->client) {
return;
}
sentry_path_t *path = make_attachment_path(data->run_path, attachment);
if (!path) {
return;
}
data->client->RemoveAttachment(
base::FilePath(SENTRY_PATH_PLATFORM_STR(path)));

if (sentry__attachment_get_bytes(attachment, nullptr)) {
if (sentry__path_remove(path) != 0) {
SENTRY_WARNF(
"failed to remove crashpad attachment \"%s\"", path->path);
}
if (sentry_path_t *dir = sentry__path_dir(path)) {
sentry__path_remove(dir);
sentry__path_free(dir);
}
}
sentry__path_free(path);
}
#endif

static int
crashpad_backend_startup(
sentry_backend_t *backend, const sentry_options_t *options)
Expand Down Expand Up @@ -1028,12 +1122,38 @@ crashpad_backend_startup(
crashpad::TriState::kEnabled);
}

#if defined(SENTRY_PLATFORM_WINDOWS) || defined(SENTRY_PLATFORM_LINUX) \
|| defined(SENTRY_PLATFORM_MACOS)
sentry_scope_observer_t *observer = sentry__scope_observer_new();
if (observer) {
observer->data = data;
observer->add_attachment = add_attachment;
observer->remove_attachment = remove_attachment;
SENTRY_WITH_SCOPE_MUT_NO_FLUSH (scope) {
if (sentry__scope_add_observer(scope, observer)) {
data->scope_observer = observer;
}
}
}
#endif

return 0;
}

static void
crashpad_backend_shutdown(sentry_backend_t *backend)
{
auto *data = static_cast<crashpad_state_t *>(backend->data);
#if defined(SENTRY_PLATFORM_WINDOWS) || defined(SENTRY_PLATFORM_LINUX) \
|| defined(SENTRY_PLATFORM_MACOS)
if (data->scope_observer) {
SENTRY_WITH_SCOPE_MUT_NO_FLUSH (scope) {
sentry__scope_remove_observer(scope, data->scope_observer);
}
data->scope_observer = nullptr;
}
#endif

#ifdef SENTRY_PLATFORM_LINUX
// restore signal handlers to their default state
for (const auto signal : g_CrashSignals) {
Expand All @@ -1043,7 +1163,7 @@ crashpad_backend_shutdown(sentry_backend_t *backend)
}
#endif

crashpad_state_dtor(static_cast<crashpad_state_t *>(backend->data));
crashpad_state_dtor(data);

#ifdef SENTRY_PLATFORM_LINUX
g_signal_stack.ss_flags = SS_DISABLE;
Expand Down Expand Up @@ -1214,101 +1334,6 @@ crashpad_backend_prune_database(sentry_backend_t *backend)
crashpad::PruneCrashReportDatabase(data->db, &condition);
}

#if defined(SENTRY_PLATFORM_WINDOWS) || defined(SENTRY_PLATFORM_LINUX) \
|| defined(SENTRY_PLATFORM_MACOS)
static sentry_path_t *
make_attachment_path(const sentry_path_t *run_path, sentry_value_t attachment)
{
if (!sentry__attachment_get_bytes(attachment, nullptr)) {
return sentry__attachment_make_path(attachment);
}

sentry_uuid_t id = sentry__attachment_get_id(attachment);
const char *filename = sentry__attachment_get_filename(attachment);
if (!run_path || sentry_uuid_is_nil(&id)
|| sentry__string_empty(filename)) {
return nullptr;
}

char uuid[37];
sentry_uuid_as_string(&id, uuid);
sentry_path_t *dir = sentry__path_join_str(run_path, uuid);
sentry_path_t *path = dir ? sentry__path_join_str(dir, filename) : nullptr;
sentry_path_t *parent = path ? sentry__path_dir(path) : nullptr;
bool valid = parent && sentry__path_eq(parent, dir);
sentry__path_free(parent);
sentry__path_free(dir);
if (!valid) {
sentry__path_free(path);
return nullptr;
}
return path;
}

static void
crashpad_backend_add_attachment(sentry_backend_t *backend,
sentry_value_t attachment, const sentry_options_t *UNUSED(options))
{
auto *data = static_cast<crashpad_state_t *>(backend->data);
if (!data || !data->client) {
return;
}

size_t bytes_len = 0;
const char *bytes = sentry__attachment_get_bytes(attachment, &bytes_len);
sentry_path_t *path = make_attachment_path(data->run_path, attachment);
if (!path) {
const char *filename = sentry__attachment_get_filename(attachment);
SENTRY_WARNF("failed to create path for crashpad attachment \"%s\"",
filename ? filename : "<unknown>");
return;
}

if (bytes) {
sentry_path_t *dir = sentry__path_dir(path);
int rv = dir ? sentry__path_create_dir_all(dir) : 1;
sentry__path_free(dir);
if (rv != 0 || sentry__path_write_buffer(path, bytes, bytes_len) != 0) {
SENTRY_WARNF(
"failed to write crashpad attachment \"%s\"", path->path);
sentry__path_remove(path);
sentry__path_free(path);
return;
}
}
data->client->AddAttachment(base::FilePath(SENTRY_PATH_PLATFORM_STR(path)));
sentry__path_free(path);
}

static void
crashpad_backend_remove_attachment(
sentry_backend_t *backend, sentry_value_t attachment)
{
auto *data = static_cast<crashpad_state_t *>(backend->data);
if (!data || !data->client) {
return;
}
sentry_path_t *path = make_attachment_path(data->run_path, attachment);
if (!path) {
return;
}
data->client->RemoveAttachment(
base::FilePath(SENTRY_PATH_PLATFORM_STR(path)));

if (sentry__attachment_get_bytes(attachment, nullptr)) {
if (sentry__path_remove(path) != 0) {
SENTRY_WARNF(
"failed to remove crashpad attachment \"%s\"", path->path);
}
if (sentry_path_t *dir = sentry__path_dir(path)) {
sentry__path_remove(dir);
sentry__path_free(dir);
}
}
sentry__path_free(path);
}
#endif

void
sentry__backend_preload(void)
{
Expand Down Expand Up @@ -1340,11 +1365,6 @@ sentry__backend_new(void)
backend->get_last_crash_func = crashpad_backend_last_crash;
backend->process_old_run_func = crashpad_backend_process_old_run;
backend->prune_database_func = crashpad_backend_prune_database;
#if defined(SENTRY_PLATFORM_WINDOWS) || defined(SENTRY_PLATFORM_LINUX) \
|| defined(SENTRY_PLATFORM_MACOS)
backend->add_attachment_func = crashpad_backend_add_attachment;
backend->remove_attachment_func = crashpad_backend_remove_attachment;
#endif
backend->data = data;
backend->can_capture_after_shutdown = true;

Expand Down
Loading
Loading