Skip to content

fix: flaky TestPrunePromptTermination test - #7168

Open
hirehamir wants to merge 1 commit into
docker:masterfrom
hirehamir:fix/flaky-test-prune-prompt-termination
Open

hirehamir wants to merge 1 commit into
docker:masterfrom
hirehamir:fix/flaky-test-prune-prompt-termination

Conversation

@hirehamir

@hirehamir hirehamir commented Aug 7, 2026 •

Copy link
Copy Markdown
Contributor

- What I did

Fixes #5802

- How I did it

I kept the write end of the pipe alive for the duration of the test with

defer w.Close()

- How to verify it

# without the changes from this branch: fails most runs
# with the changes from this branch: 0 failures
GOGC=1 GOMEMLIMIT=8MiB go test ./cli/command/container/ -run TestContainerPrunePromptTermination -count=40 -v
GC forced (GOGC=1 GOMEMLIMIT=8MiB) GC off (GOGC=off)
without this change 33 of 40 fail 0 of 40 fail
with this change 0 of 40 fail 0 of 40 fail

@codecov-commenter

codecov-commenter commented Aug 7, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 0% with 5 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
internal/test/cmd.go 0.00% 5 Missing ⚠️

📢 Thoughts on this report? Let us know!

@GitNimay

GitNimay commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

I can confirm this fixes the flake, which also hit CI on #7408 (TestSystemPrunePromptTermination). The discarded write end of the pipe is garbage-collected, its finalizer closes it, and the prompt reads EOF (treated as "no"), so the command returns "prune has been cancelled" instead of prompt.ErrTerminated.

Reproduce on master with:

GOGC=1 go test -race -count=200 -run PromptTermination ./cli/command/system ./cli/command/image

That gave 11 failures on master, and 0 with the write end kept open.

Two things you may want to add here:

  • cmd/docker-trust/internal/test/cmd.go has an identical copy of TerminatePrompt with the same bug.
  • Under -race, the cli.OutBuffer().Len() check in the helper races with the prompt that is still writing to the buffer. The writer hook already guarantees a write happened, so that check can be dropped.

This is the flake tracked in #5802.

@hirehamir

Copy link
Copy Markdown
Contributor Author

That makes sense. I'll add those changes right now.

@hirehamir

Copy link
Copy Markdown
Contributor Author

@Benehiko anything else you'd like to see here?

@hirehamir
hirehamir force-pushed the fix/flaky-test-prune-prompt-termination branch from 0389b98 to 3f83a0c Compare October 19, 2026 16:30

@Benehiko Benehiko left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for tracking this down! The root cause checks out: the discarded write end gets finalized by the GC, and the prompt reads EOF and treats it as "no". Dropping the OutBuffer().Len() check is also safe, since the writer hook only fires after the write to the buffer has completed.

Before this can be merged:

  • The commits need to be signed off for the DCO check; none of them currently has a Signed-off-by trailer.
  • Please squash the three commits into one. They are all part of the same fix, and the last one ("fix identical issue in internal/test/cmd.go") is misleading since that file was already changed in the first commit. A single commit whose message explains the cause (the unreferenced write end is closed by its GC finalizer, so the prompt reads EOF) will be much more useful in git log.

You can do both at once with git rebase -i --signoff master (mark the later commits as squash), then force-push.

Comment thread internal/test/cmd.go Outdated
Comment on lines +30 to +34
r, w, err := os.Pipe()
assert.NilError(t, err)

// Keep the write end alive for the duration of the test.
defer w.Close()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

r is never closed, so every call to TerminatePrompt leaks a file descriptor. Could we register cleanup for both ends of the pipe with t.Cleanup instead of deferring only w.Close()?

Suggested change
r, w, err := os.Pipe()
assert.NilError(t, err)
// Keep the write end alive for the duration of the test.
defer w.Close()
r, w, err := os.Pipe()
assert.NilError(t, err)
t.Cleanup(func() {
_ = w.Close()
_ = r.Close()
})

Comment thread cmd/docker-trust/internal/test/cmd.go Outdated
Comment on lines +30 to +34
r, w, err := os.Pipe()
assert.NilError(t, err)

// Keep the write end alive for the duration of the test.
defer w.Close()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as in internal/test/cmd.go: r is never closed here either. Could we clean up both ends with t.Cleanup?

Suggested change
r, w, err := os.Pipe()
assert.NilError(t, err)
// Keep the write end alive for the duration of the test.
defer w.Close()
r, w, err := os.Pipe()
assert.NilError(t, err)
t.Cleanup(func() {
_ = w.Close()
_ = r.Close()
})

@hirehamir

Copy link
Copy Markdown
Contributor Author

You're welcome! I'll make those changes right now. Thanks for including the git rebase -i --signoff command.

TerminatePrompt created a pipe for the prompt's stdin but discarded the
write end. Once the garbage collector finalized it, the write end was
closed, the prompt read EOF and treated it as "no", and the command
returned "prune has been cancelled" instead of prompt.ErrTerminated.

This keeps both ends of the pipe referenced and closes them in t.Cleanup.

This change also drops the OutBuffer().Len() check:
the writer hook only fires after
the write has completed, so the check proved nothing, and it raced with
the prompt's later writes under -race.

This change also applies the same fix to the identical copy in cmd/docker-trust.

Signed-off-by: Hamir <hirehamir@gmail.com>
@hirehamir
hirehamir force-pushed the fix/flaky-test-prune-prompt-termination branch from 3f83a0c to dd50814 Compare October 22, 2026 17:23
@hirehamir
hirehamir requested a review from Benehiko October 22, 2026 17:43
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 test: TestPrunePromptTermination

4 participants