Skip to content

batch_processing_with_kafka.end_to_end wedged CIKafka for 10+ minutes — hang is outside its own 60s tracked timeout #4116

Description

@jeremydmiller

Caught by the #4108 instrumentation on its first capped job (run 32786336368, CIKafka, 2026-08-24): the job died at the 20-minute cap with 297/302 tests done and one in flight — and this time the log names it:

23:38:12 [INF]  11m46s — 297/302 done, 1 in flight (lane 0), longest running: Wolverine.Kafka.Tests.batch_processing_with_kafka.end_to_end (188s)
23:40:04 [INF]  STALLED: Wolverine.Kafka.Tests.batch_processing_with_kafka.end_to_end has been in flight 300s on lane 0 (pid 3814)
...
23:44:50 [INF]  18m24s — 297/302 done, 1 in flight (lane 0), longest running: Wolverine.Kafka.Tests.batch_processing_with_kafka.end_to_end (586s)

Still climbing at 586s when the cap killed the job. This is the #4083 shape (a batch that wedges reports nothing) finally with a name on it, and very plausibly the same job that produced the earlier unexplained CIKafka cap-kills.

The sharp clue

The test (src/Transports/Kafka/Wolverine.Kafka.Tests/batch_processing_with_kafka.cs) puts a .Timeout(60.Seconds()) on its tracked session — yet it was in flight for 10+ minutes. So the hang is not the message wait, which would have thrown at 60s. The wedge has to be either:

  1. AlbaHost.For<Program> startup — e.g. a Kafka admin/consumer connection retrying unboundedly while the broker container is degraded, before the tracked session even starts; or
  2. await using host teardown — the tracked session times out (or completes), and disposal then hangs stopping a Kafka listener/producer. This is the CIPulsar wedges in PulsarNativeReliabilityTests — DotPulsar producers stall in Setup, and the test's 1000s timeout outlives the 20-minute job cap #4100 Pulsar shape exactly: an await parked on the GC heap waiting for a broker state change that never comes.

Teardown is the more likely suspect given the test's own assertions never reported a failure — a 60s timeout throwing inside the attempt would surface as a failed test, not a silent wedge (though an exception thrown while the host refuses to dispose would also present this way).

Getting the async stacks next time

The dump that would settle this didn't happen: the runner's SIGTERM never reached the build process's cancellation handler (the bash → build.sh → dotnet run chain forwards nothing). #4115 fixes that with a pid-handshake relay — once merged, the next recurrence should produce dumpasync --coalesce output for pid-in-hand in the job log (grep '\[stall\]'), plus a partial ledger naming the test in the artifact.

Until then it can be chased locally: run CIKafka, and if it wedges, dotnet-dump collect -p <pid from the STALLED line> + dumpasync --coalesce.

Related: #4083 (the shape), #4100 (the Pulsar precedent and the dumpasync method), #4108 (the instrumentation that named it), #4115 (the relay that will capture it).

🤖 Generated with Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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