Skip to content

Conversation

@laurazard
Copy link
Collaborator

@laurazard laurazard commented Jun 30, 2023

- What I did

Fixes the flaky TestCloseWhileWriting and TestCloseWhileReading tests.

- How I did it

Changes the Read and Write error handling logic to return the original error while closing the connection. We still skip calling handleEOF if already closing the connection.

- How to verify it

go test -v ./..., and make sure everything still works.

- Description for the changelog

- A picture of a cute animal (not mandatory but encouraged)

@codecov-commenter
Copy link

Codecov Report

Merging #4394 (ee888c6) into master (cb1def7) will decrease coverage by 0.01%.
The diff coverage is 100.00%.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #4394      +/-   ##
==========================================
- Coverage   59.37%   59.37%   -0.01%     
==========================================
  Files         288      286       -2     
  Lines       24746    24746              
==========================================
- Hits        14693    14692       -1     
  Misses       9169     9169              
- Partials      884      885       +1     

// to return an io.EOF
return 0, io.EOF
// we don't want to call onEOF
return n, err
Copy link
Member

Choose a reason for hiding this comment

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

Err may be nil here; do we need to return a io.EOF in that case? (Thinking out loud if we need an io.EOF for calling code)

if err == nil {
    return io.EOF
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

No, if the read didn't return an error then it's fine to not return one here. This was the original behavior, and subsequent reads will fail regardless with a file closed/pipe closed error.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

In normal operation, it will only be closing if an EOF was already returned triggering the transport layer to call Close regardless. This special handling is only meant to keep us from calling handleEOF twice.

Copy link
Member

Choose a reason for hiding this comment

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

Thanks for looking! The original comment triggered my curiosity, so wanted to check 😅 👍

Copy link
Member

@thaJeztah thaJeztah left a comment

Choose a reason for hiding this comment

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

minor comment on the test, but otherwise LGTM


writeErr := <-writeErrC
assert.ErrorContains(t, writeErr, "EOF")
assert.ErrorContains(t, writeErr, "file already closed")
Copy link
Member

Choose a reason for hiding this comment

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

Should we be using one of these for this?

https://github.com/golang/go/blob/18e17e2cb12837ea2c8582ecdb0cc780f49a1aac/src/io/fs/fs.go#L141
https://github.com/golang/go/blob/18e17e2cb12837ea2c8582ecdb0cc780f49a1aac/src/os/error.go#L24

Suggested change
assert.ErrorContains(t, writeErr, "file already closed")
assert.Check(t, is.ErrorIs(writeErr, fs.ErrClosed))


readErr := <-readErrC
assert.ErrorContains(t, readErr, "EOF")
assert.ErrorContains(t, readErr, "file already closed")
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
assert.ErrorContains(t, readErr, "file already closed")
assert.Check(t, is.ErrorIs(readErr, fs.ErrClosed))

Changes the `Read` and `Write` error handling
logic to return the original error while closing
the connection. We still skip calling `handleEOF`
if already closing the connection.

Fixes the flaky `TestCloseWhileWriting` and
`TestCloseWhileReading` tests.

Co-authored-by: Sebastiaan van Stijn <github@gone.nl>
Signed-off-by: Laura Brehm <laurabrehm@hey.com>
Copy link
Member

@thaJeztah thaJeztah left a comment

Choose a reason for hiding this comment

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

I applied my suggestions in the test

LGTM

@laurazard
Copy link
Collaborator Author

Thanks! I was away from a keyboard, appreciate it ❤️

@thaJeztah thaJeztah merged commit dc2eb3b into docker:master Jun 30, 2023
@thaJeztah
Copy link
Member

Preparing a cherry-pick; will be up in a minute 👍

@thaJeztah
Copy link
Member

@vvoland
Copy link
Collaborator

vvoland commented Jul 4, 2023

Looks like it's still flaky - I just got a test failure in a freshly rebased PR: https://github.com/docker/cli/actions/runs/5454066267/jobs/9923693780?pr=4331

 85.59 === Failed
85.59 === FAIL: cli/connhelper/commandconn TestCloseWhileWriting (0.00s)
85.59     commandconn_unix_test.go:182: assertion failed: expected error to contain "file already closed", got "write |1: broken pipe"

\cc @laurazard

@laurazard
Copy link
Collaborator Author

Thanks @vvoland. I'll TAL when I get a change.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Flaky test: TestCloseWhileWriting, TestCloseWhileReading

4 participants