Skip to content

Make SDK re-init cheap: avoid full-timeout executor close and duplicate thread sets #5715

Description

@runningcode

Problem

Customers initialize Sentry twice at startup (minimal init early to catch crashes, full init once async config is available — does exactly this). A customer cold-start trace (Galaxy A14 / API 34, TTID 1723 ms, method-level tracing) shows re-init is expensive:

  • io.sentry.Sentry#init runs twice: main thread @396 ms (16.7 ms) and a coroutine thread @587 ms (47.7 ms).
  • The re-init triggers two io.sentry.SentryExecutorService#close calls that each block for the full 2000 ms (shutdownTimeoutMillis default) — awaitTermination never completes, likely because the old executor queue is stuffed with scope-persistence work (or a task never terminates). Both ran on old SentryExecutorS threads, so no main-thread block here, but two threads spin for 2 s and any work queued behind them is lost/delayed.
  • The second init spawns a complete duplicate thread set (2× transport SentryAsyncConn, 2× frame-metrics etricsCollector, 3× SentryExecutorS observed).

Proposal (investigate)

  • Find out why close hits the full timeout (long-running queued task? persistence backlog? non-interruptible IO) — Scopes.closeSentryOptions/SentryExecutorService.close(shutdownTimeoutMillis).
  • Fast-close path for the re-init case: drain-or-abandon semantics instead of a blocking awaitTermination(2000) (crash-relevant tasks excepted).
  • Investigate reusing executor/transport/collector threads across re-init when compatible options allow, instead of tearing down + respawning the world.
  • Consider documenting/supporting the "init twice" pattern explicitly (relates to InitUtil.shouldInit priorities and forceInit).

Notes

Metadata

Metadata

Assignees

No one assigned

    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