Skip to content

Commit

Permalink
copy: improve error detection from closed pipes
Browse files Browse the repository at this point in the history
If we get io.ErrClosedPipe in pushWriter.Write, there are three possible
scenarios:

- The request has failed, we need to attempt a reset, so we can expect a
  new pipe incoming on pipeC.
- The request has failed, we don't need to attempt a reset, so we can
  expect an incoming error on errC.
- Something else externally has called Close, so we can expect the done
  channel to be closed.

This patch ensures that we block for as long as possible (while still
handling each of the above cases, so we avoid hanging), to make sure
that we properly return an appropriate error message each time.

Signed-off-by: Justin Chadwell <me@jedevc.com>
  • Loading branch information
jedevc committed Mar 4, 2024
1 parent d081da8 commit 2577207
Showing 1 changed file with 16 additions and 3 deletions.
19 changes: 16 additions & 3 deletions remotes/docker/pusher.go
Original file line number Diff line number Diff line change
Expand Up @@ -424,9 +424,22 @@ func (pw *pushWriter) Write(p []byte) (n int, err error) {
// if the pipe is closed, we might have the original error on the error
// channel - so we should try and get it
select {
case err2 := <-pw.errC:
err = err2
default:
case <-pw.done:
case err = <-pw.errC:
case p := <-pw.pipeC:
pw.pipe.CloseWithError(content.ErrReset)
pw.pipe = p

// If content has already been written, the bytes
// cannot be written again and the caller must reset
status, err := pw.tracker.GetStatus(pw.ref)
if err != nil {
return 0, err
}
status.Offset = 0
status.UpdatedAt = time.Now()
pw.tracker.SetStatus(pw.ref, status)
return 0, content.ErrReset
}
}
status.Offset += int64(n)
Expand Down

0 comments on commit 2577207

Please sign in to comment.