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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions