Skip to content

Poll the chaincode container listings in the e2e suite - #5557

Merged
pfi79 merged 1 commit into
mainfrom
e2e-eventually-container-list
Sep 8, 2026
Merged

Poll the chaincode container listings in the e2e suite#5557
pfi79 merged 1 commit into
mainfrom
e2e-eventually-container-list

Conversation

@ryjones

@ryjones ryjones commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

The e2e suite reads docker's running-container list once and asserts on it in four places, and each single read races the peer.

The spec "recreates terminated chaincode containers" removes every chaincode container, invokes once per peer so that each peer relaunches its chaincode, and then lists the running chaincode containers, expecting one per peer. The peer treats a chaincode as launched as soon as the chaincode process registers over gRPC: RuntimeLauncher.Launch returns on launchState.Done() while the goroutine that called DockerVM.Start is still inside ContainerStart, and dockerd only adds a container to the running list at the end of its start path, after persisting the container state. In that window the chaincode is registered and endorsing but docker ps does not list it. Endorsement, ordering, commit and event delivery all happen on localhost and fit inside the window whenever dockerd's tail takes more than a few tens of milliseconds, so the listing taken right after the last invoke can come back one container short:

Expected <[]container.Summary | len:3, cap:4>: [...] to have length 4

Recording docker events alongside the spec shows dockerd emitting its start event for each relaunched container about 20 ms after the peer has already finished executing chaincode inside it, and in failing runs the last container's start event is timestamped after the listing. On hosts with a slow dockerd start path (docker inside an unprivileged LXC container on ZFS) the spec fails about half the time, on main and on unrelated branches alike; the other e2e specs pass every time.

The spec "basic lifecycle operations for chaincode install and update" has the same shape twice, listing the containers right after the init invoke that launches them, and a third read in the other direction: after a definition upgrade it expects the superseded containers to be gone, but the peer stops those from the lifecycle custodian's background worker, not as part of block commit, so nothing orders that stop before the listing either.

Poll all four listings with Eventually through a shared helper, as the rest of the suite does for side effects, and check the recreated container IDs against the originals as before.

Type of change

  • Test update

Related issues

Fixes #5556

The e2e suite reads docker's running-container list once and asserts on
it in four places, and each single read races the peer.

The spec "recreates terminated chaincode containers" removes every
chaincode container, invokes once per peer so that each peer relaunches
its chaincode, and then lists the running chaincode containers, expecting
one per peer.  The peer treats a chaincode as launched as soon as the
chaincode process registers over gRPC: RuntimeLauncher.Launch returns on
launchState.Done() while the goroutine that called DockerVM.Start is
still inside ContainerStart, and dockerd only adds a container to the
running list at the end of its start path, after persisting the container
state.  In that window the chaincode is registered and endorsing but
`docker ps` does not list it.  Endorsement, ordering, commit and event
delivery all happen on localhost and fit inside the window whenever
dockerd's tail takes more than a few tens of milliseconds, so the listing
taken right after the last invoke can come back one container short:

  Expected <[]container.Summary | len:3, cap:4>: [...] to have length 4

Recording docker events alongside the spec shows dockerd emitting its
`start` event for each relaunched container about 20 ms after the peer
has already finished executing chaincode inside it, and in failing runs
the last container's `start` event is timestamped after the listing.  On
hosts with a slow dockerd start path (docker inside an unprivileged LXC
container on ZFS) the spec fails about half the time, on main and on
unrelated branches alike; the other e2e specs pass every time.

The spec "basic lifecycle operations for chaincode install and update"
has the same shape twice, listing the containers right after the init
invoke that launches them, and a third read in the other direction: after
a definition upgrade it expects the superseded containers to be gone, but
the peer stops those from the lifecycle custodian's background worker,
not as part of block commit, so nothing orders that stop before the
listing either.

Poll all four listings with Eventually through a shared helper, as the
rest of the suite does for side effects, and check the recreated
container IDs against the originals as before.

Assisted-by: anthropic:claude-fable-5-1
Signed-off-by: Ry Jones <ry@linux.com>
@ryjones
ryjones marked this pull request as ready for review September 8, 2026 14:51
@ryjones
ryjones requested a review from a team as a code owner September 8, 2026 14:51
@ryjones
ryjones requested review from a team September 8, 2026 15:45
@pfi79
pfi79 merged commit e037166 into main Sep 8, 2026
56 of 59 checks passed
@ryjones
ryjones deleted the e2e-eventually-container-list branch September 8, 2026 15:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Flaky e2e spec: container listing races dockerd start after chaincode relaunch

2 participants