Skip to content

Windows/crashpad: breadcrumbs and scope changes block the calling thread with no upper bound (WaitNamedPipe(NMPWAIT_WAIT_FOREVER)) while crashpad_handler is busy #2182

Closed

Description

@EgemenNair

Environment

  • sentry-native a185ce8, as bundled in sentry-unity 4.8.0
  • Windows 10/11, crashpad backend
  • Unity 6 game, native app-hang tracking on

What happens

Each of these calls makes a synchronous named-pipe round trip to crashpad_handler on the calling thread:

  • sentry_add_breadcrumb: crashpad_backend_add_breadcrumb → CrashpadClient::AppendAttachment
  • every scope change (sentry_set_extra, sentry_set_tag, ...): crashpad_backend_flush_scope → CrashpadClient::WriteAttachment

When the pipe is busy, SendPayloadToCrashHandlerServer (util/win/registration_protocol_win.cc:163-169 on getsentry/crashpad master) retries ERROR_PIPE_BUSY with WaitNamedPipe(pipe_name, NMPWAIT_WAIT_FOREVER). The wait has no upper bound.

The pipe is busy more often than the design intends:

  • The server has kPipeInstances = 2 (util/win/exception_handler_server.h:146).
  • HandleWriteAttachment and HandleAppendAttachment acknowledge before disk I/O. The comment there says the purpose is to keep the client from blocking on slow disk I/O.
  • But the disk write then runs on the same pipe service thread. The instance is only disconnected and reconnected after the write finishes.

So when two writes are in flight, the third caller waits for the handler's disk. The trigger can be a burst of breadcrumbs, a slow disk, an antivirus scan, or a handler that gets no CPU.

SDKs call these functions from the app's main thread; in Unity, every log line becomes a breadcrumb. The result is an app hang of unbounded length. In production we see it as AppHang events (sentry-native's own detector) with the main thread in WaitNamedPipeW, from sentry.dll, lasting 5 s and more. We had 4 events from 3 users in one release.

Repro

  1. Open both instances of \\.\pipe\crashpad_<pid>_* from another process (CreateFile twice, write nothing).
  2. Call sentry_add_breadcrumb or sentry_set_extra. It blocks until the instances are released. We measured 12-13 s for a 14 s hold, and the app-hang detector reports it.

Suggestions

  • Bound the wait: use a finite WaitNamedPipe timeout, then drop or defer the write.
  • Or queue attachment writes to a background thread inside the client.

Workaround

We moved IScopeObserver calls to our own background thread. The main-thread write now takes about 0.02 ms in the same repro, and the hang report still carries the full scope and breadcrumbs.

Activity

  1. linear-code commented on Oct 8, 2026

    @linear-code
  2. added
    Bugsomething isn't working as it should
    on Oct 8, 2026
  3. jpnurmi commented on Oct 9, 2026

    @jpnurmi
    Collaborator

    Thanks for the report! We'll take a look.

  4. moved this from Waiting for: Product Owner to No status in GitHub Issues with 👀 3on Oct 9, 2026
  5. self-assigned this
    on Oct 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Bugsomething isn't working as it should

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions