From 7c955ee84e032da18e8e27efa8132c248bcae965 Mon Sep 17 00:00:00 2001 From: Nelson Osacky Date: Wed, 11 Nov 2026 16:53:34 +0100 Subject: [PATCH 1/2] fix(android): Don't swallow interrupts while flushing a startup crash After a startup crash, SendCachedEnvelopeIntegration blocks the thread that calls Sentry.init until the cached envelopes are sent. If that thread was interrupted, future.get() cleared the interrupt and the trailing catch (Throwable) swallowed it, so the caller never saw it. It also logged that cached events will not be sent, although the task keeps sending them. Catch InterruptedException next to the timeout, restore the interrupt and continue in the background. Co-Authored-By: Claude Opus 5.5 --- .../core/SendCachedEnvelopeIntegration.java | 7 ++++++ .../core/SendCachedEnvelopeIntegrationTest.kt | 22 +++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/SendCachedEnvelopeIntegration.java b/sentry-android-core/src/main/java/io/sentry/android/core/SendCachedEnvelopeIntegration.java index 8eea2d71047..05352be394c 100644 --- a/sentry-android-core/src/main/java/io/sentry/android/core/SendCachedEnvelopeIntegration.java +++ b/sentry-android-core/src/main/java/io/sentry/android/core/SendCachedEnvelopeIntegration.java @@ -157,6 +157,13 @@ private void sendCachedEnvelopes( options .getLogger() .log(SentryLevel.DEBUG, "Synchronous send timed out, continuing in the background."); + } catch (InterruptedException e) { + // We don't own the calling thread, so keep its interrupt for the code that does + Thread.currentThread().interrupt(); + options + .getLogger() + .log( + SentryLevel.DEBUG, "Synchronous send interrupted, continuing in the background."); } } options.getLogger().log(SentryLevel.DEBUG, "SendCachedEnvelopeIntegration installed."); diff --git a/sentry-android-core/src/test/java/io/sentry/android/core/SendCachedEnvelopeIntegrationTest.kt b/sentry-android-core/src/test/java/io/sentry/android/core/SendCachedEnvelopeIntegrationTest.kt index df9ce60883e..32b38764626 100644 --- a/sentry-android-core/src/test/java/io/sentry/android/core/SendCachedEnvelopeIntegrationTest.kt +++ b/sentry-android-core/src/test/java/io/sentry/android/core/SendCachedEnvelopeIntegrationTest.kt @@ -1,5 +1,6 @@ package io.sentry.android.core +import com.google.common.truth.Truth.assertThat import io.sentry.IConnectionStatusProvider import io.sentry.IConnectionStatusProvider.ConnectionStatus import io.sentry.ILogger @@ -137,6 +138,27 @@ class SendCachedEnvelopeIntegrationTest { verify(fixture.sender).send() } + @Test + fun `when interrupted while awaiting the task, keeps the interrupt and continues in the background`() { + // the delay keeps the task running, so the wait for it sees the interrupt + val sut = fixture.getSut(hasStartupCrashMarker = true, delaySend = 500) + + Thread.currentThread().interrupt() + try { + sut.register(fixture.scopes, fixture.options) + + assertThat(Thread.currentThread().isInterrupted).isTrue() + } finally { + // don't leak the interrupt into other tests + Thread.interrupted() + } + verify(fixture.logger) + .log(eq(DEBUG), eq("Synchronous send interrupted, continuing in the background.")) + + await.untilFalse(fixture.flag) + verify(fixture.sender).send() + } + @Test fun `registers for network connection changes`() { val sut = From 212143e3ba77b4bc9ed3deb1dc9251ba0471e7af Mon Sep 17 00:00:00 2001 From: Nelson Osacky Date: Wed, 11 Nov 2026 16:54:09 +0100 Subject: [PATCH 2/2] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bdb17f37298..eadd4444d55 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,7 @@ ### Fixes +- Keep the interrupt of the thread that calls `Sentry.init` when it is interrupted while the SDK waits for cached events to be sent after a startup crash ([#6568](https://github.com/getsentry/sentry-java/pull/6568)) - Capture scroll breadcrumbs for `LazyColumn`, `LazyRow`, lazy grids, and `Pager` on Jetpack Compose foundation 1.10+ ([#6548](https://github.com/getsentry/sentry-java/pull/6548)) - Prevent the main thread from potentially hanging during app start or when returning to the foreground if Android is slow to register the SDK's network or telephony listeners. `Sentry.init`, Session Replay, and capturing events no longer wait for that registration ([#6537](https://github.com/getsentry/sentry-java/pull/6537)) - Add opt-in support for matching GraphQL ignored error types against classification specifications via `sentry.graphql.enable-specification-error-type-filtering` ([#6092](https://github.com/getsentry/sentry-java/pull/6092))