Skip to content

PreparedModeAuthenticationFunctionalTest hangs intermittently on V2/V2, silently consuming the job timeout #932

Description

@jbachorik

Summary

PreparedModeAuthenticationFunctionalTest intermittently hangs on its V2/V2 parameterisations,
consuming the full 30-minute job budget and producing no failing assertion, no stack trace, and
several orphaned JVMs. Seen on test (17.0.19-tem) in CI; not reproduced locally in one attempt on
17.0.14.

Evidence

Same PR, three runs of the same tier:

Run Result
30381203688 job 90349867449 hung, cancelled at 30m
30381203688 job 90359031612 (re-run) hung, cancelled at 30m
30391315946 passed in 4m47s

develop passes the same tier in 4m16s, so ~4–5 minutes is the normal duration and 30 minutes is a
stall rather than slowness.

It is not a fixed case. The first run stalled on client v2, server v2, auto=false, supplied token=true; the re-run passed that one and stalled on a later V2/V2 parameterisation, on a
different executor thread.

Last output before the silence, both times:

PreparedModeAuthenticationFunctionalTest > ... > client v2, server v2, ...
    [pool-6-thread-1] INFO io.btrace.client.Client - Successfully started BTrace probe: OnTimerArgTest.java
                                   ← ~25 minutes of nothing
##[error]The operation was canceled.

Job cleanup then reports:

Terminate orphan process: pid (3339) (java)      ... seven of these

So authentication, negotiation and probe submission all completed. The stall is after that.

Why this is worse than a normal flake

The failure is silent. There is no assertion failure and no thread dump, so localising it required
reading the raw job log and comparing timestamps. Every occurrence costs the whole job budget.

It also reaches the release path: release-smoke runs after the operator has published to Maven
Central and finalize-tag depends on it, so a stall there leaves artifacts on Central with no tag,
no GitHub release and no SDKMAN update — the same shape as a failure, but with no diagnostic.

Unverified hypothesis

Offered as a starting point, not a conclusion — it has not been reproduced.

Every wait inside assertProbeRoundTrip is bounded (started.get(20s), submission.get(10s)), so
a 25-minute silence cannot be the test awaiting an assertion. The probe submission runs on
Executors.newSingleThreadExecutor(), whose threads are non-daemon, and executor.shutdownNow()
interrupts — but a thread blocked in socket I/O does not respond to interrupt. A surviving
non-daemon thread would keep the test JVM alive, so the Gradle worker never exits and the build
stalls with nothing to report. The orphaned JVMs at cleanup are consistent with this.

Suggested changes

Independent of root cause:

  1. Per-test timeout in the integration harness, so a stall becomes a fast, attributable failure
    with a stack dump naming the blocked thread instead of a silent 30-minute job.
  2. Daemon threads for the test executors, so a thread stuck in socket I/O cannot hold the test
    JVM open.
  3. Consider a thread dump on timeout, which would have made this a one-line diagnosis.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions