Skip to content

Core re-entrancy guard for user callbacks (beforeSend/beforeBreadcrumb/beforeSendLog) #5738

Description

@runningcode

Problem

A user beforeSend / beforeBreadcrumb / beforeSendLog callback that triggers another SDK capture — directly, or transitively through a logging integration that routes back into Sentry (Timber's SentryTimberTree, or the Gradle plugin's logcat instrumentation) — recurses until a StackOverflowError. The callbacks run synchronously on the caller thread with only a try/catch; nothing prevents re-entrant capture.

This is the same class of bug as the logcat crash SDK-CRASHES-JAVA-3T3H (fixed per-integration in #5734). Investigation confirmed Timber has it too, and the core offers no protection, so we fix the whole class once in the core.

Fix

SentryCallbackReentrancyGuard: a shared thread-local flag set only around each callback's execute(...). Capture entry points (SentryClient.captureEvent/captureTransaction/captureLog, Scope.addBreadcrumb) drop a nested capture while the flag is active, breaking the loop for every capture type. Event-processor captures run outside the flag and are unaffected.

Behavioral change: a capture a callback makes intentionally is dropped while that callback runs (logged at DEBUG). Dropping rather than sending is deliberate — bypassing beforeSend would risk unscrubbed PII. Makes the per-integration SentryLogcatAdapter guard redundant.

Covered by regression tests in SentryClientTest, ScopeTest, and an end-to-end SentryTimberIntegrationTest.

Links

Metadata

Metadata

Assignees

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions