Skip to content

fix(crashpad): route client logs through sentry logger#1859

Open
jpnurmi wants to merge 3 commits into
masterfrom
jpnurmi/fix/crashpad-log-handler
Open

fix(crashpad): route client logs through sentry logger#1859
jpnurmi wants to merge 3 commits into
masterfrom
jpnurmi/fix/crashpad-log-handler

Conversation

@jpnurmi

@jpnurmi jpnurmi commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator

Forward Crashpad client log messages to the Sentry logger instead of stderr. This makes actionable Crashpad handler startup errors due to missing executable permissions, for example, visible in downstream SDKs that only capture Sentry logs, not stderr.

Before:

[sentry] DEBUG starting backend
[sentry] DEBUG background worker thread started
[sentry] DEBUG starting crashpad backend with handler "/Users/jpnurmi/Projects/sentry/sentry-playground/build/crashpad_handler"
[sentry] DEBUG using minidump URL <url>
[55318:16250687:20260713,103346.180970:FATAL spawn_subprocess.cc:222] posix_spawnp /Users/jpnurmi/Projects/sentry/sentry-playground/build/crashpad_handler: Permission denied (13)
[55303:16250469:20260713,103346.181480:WARNING spawn_subprocess.cc:247] intermediate process terminated by signal 5 (Trace/BPT trap: 5)
[55303:16250469:20260713,103346.181562:ERROR file_io.cc:107] ReadExactly: expected 8, observed 0
[sentry] WARN failed to start crashpad client handler
[sentry] WARN failed to initialize backend
[sentry] WARN `sentry_init` failed

After:

[sentry] DEBUG starting backend
[sentry] DEBUG background worker thread started
[sentry] DEBUG starting crashpad backend with handler "/Users/jpnurmi/Projects/sentry/sentry-playground/build/crashpad_handler"
[sentry] DEBUG using minidump URL <url>
[sentry] FATAL crashpad: posix_spawnp /Users/jpnurmi/Projects/sentry/sentry-playground/build/crashpad_handler: Permission denied (13)
[sentry] WARN crashpad: intermediate process terminated by signal 5 (Trace/BPT trap: 5)
[sentry] ERROR crashpad: ReadExactly: expected 8, observed 0
[sentry] WARN failed to start crashpad client handler
[sentry] WARN failed to initialize backend
[sentry] WARN `sentry_init` failed

Resolves: #792

Forward Crashpad client log messages into the Sentry logger when debug
logging is enabled, mapping severities between mini_chromium and Sentry
levels. This makes detailed crashpad_handler startup errors, such as
missing executable permissions, visible.

Resolves: #792
@github-actions

Copy link
Copy Markdown
Fails
🚫 Please consider adding a changelog entry for the next release.

Instructions and example for changelog

Please add an entry to CHANGELOG.md to the "Unreleased" section. Make sure the entry includes this PR's number.

Example:

## Unreleased

### Fixes

- route client logs through sentry logger ([#1859](https://github.com/getsentry/sentry-native/pull/1859))

If none of the above apply, you can opt out of this check by adding #skip-changelog to the PR description or adding a skip-changelog label.

Generated by 🚫 dangerJS against 6a51748

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 6a51748. Configure here.

sentry__logger_log(to_sentry_level(severity), "crashpad: %.*s",
static_cast<int>(end - start), msg.c_str() + start);
return true;
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unsafe logger use after fork

Medium Severity

The new Crashpad SetLogMessageHandler calls sentry__logger_log for every client log, including messages emitted in Crashpad’s forked intermediate process before exec. By then the SDK has already started its background worker, so this runs user logger callbacks plus non-async-signal-safe work such as malloc/stdio after a multithreaded fork, which can hang StartHandler or misbehave in custom loggers—on the same permission-denied path this change aims to surface.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 6a51748. Configure here.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ouch :( If we avoid unsafe Sentry logger callbacks from the forked intermediate process before exec, we lose exactly that one most important message that contains the information we want to make visible (permission denied).

  [sentry] DEBUG starting backend
  [sentry] DEBUG background worker thread started
  [sentry] DEBUG starting crashpad backend with handler "/Users/jpnurmi/Projects/sentry/sentry-playground/build/crashpad_handler"
  [sentry] DEBUG using minidump URL <url>
  [64238:16278493:20260713,104941.870252:FATAL spawn_subprocess.cc:222] posix_spawnp /Users/jpnurmi/Projects/sentry/sentry-playground/build/crashpad_handler: Permission denied (13)
  [sentry] WARN crashpad: intermediate process terminated by signal 5 (Trace/BPT trap: 5)
  [sentry] ERROR crashpad: ReadExactly: expected 8, observed 0
  [sentry] WARN failed to start crashpad client handler
  [sentry] WARN failed to initialize backend
  [sentry] WARN `sentry_init` failed

Comment on lines +787 to +797
logging::SetLogMessageHandler(
[](logging::LogSeverity severity, const char *UNUSED(file),
int UNUSED(line), size_t start, const std::string &msg) {
size_t end = msg.size();
if (end > start && msg[end - 1] == '\n') {
end--;
}
sentry__logger_log(to_sentry_level(severity), "crashpad: %.*s",
static_cast<int>(end - start), msg.c_str() + start);
return true;
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: The log message handler unconditionally returns true, which suppresses the abort() call for LOG_FATAL messages, allowing the process to continue running after a fatal error.
Severity: HIGH

Suggested Fix

The log message handler should return false for LOG_FATAL messages. This will allow the default behavior, which includes calling abort(), to proceed and ensure the process terminates immediately upon a fatal error.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location: src/backends/sentry_backend_crashpad.cpp#L787-L797

Potential issue: The log message handler unconditionally returns `true`. In
`mini_chromium`, if a log handler returns `true`, it prevents the default `abort()` call
for `LOG_FATAL` messages. This means that when a fatal error is logged, the process will
not terminate as expected. Instead, it will continue to execute in a potentially
inconsistent or corrupted state, which could lead to unpredictable behavior or silent
data corruption. This handler is installed globally in the parent process, affecting all
`LOG_FATAL` calls from crashpad client code.

Did we get this right? 👍 / 👎 to inform future reviews.

Update Crashpad so spawn and exec failures are reported from the parent
process instead of logging from the forked intermediate child. This keeps
handler startup diagnostics visible without invoking logger callbacks after
fork.

Co-Authored-By: OpenAI Codex <noreply@openai.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Check for permissions before starting crashpad

1 participant