Skip to content

Commit 2577207

Browse files
committed
copy: improve error detection from closed pipes
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 <[email protected]>
1 parent d081da8 commit 2577207

1 file changed

Lines changed: 16 additions & 3 deletions

File tree

remotes/docker/pusher.go

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -424,9 +424,22 @@ func (pw *pushWriter) Write(p []byte) (n int, err error) {
424424
// if the pipe is closed, we might have the original error on the error
425425
// channel - so we should try and get it
426426
select {
427-
case err2 := <-pw.errC:
428-
err = err2
429-
default:
427+
case <-pw.done:
428+
case err = <-pw.errC:
429+
case p := <-pw.pipeC:
430+
pw.pipe.CloseWithError(content.ErrReset)
431+
pw.pipe = p
432+
433+
// If content has already been written, the bytes
434+
// cannot be written again and the caller must reset
435+
status, err := pw.tracker.GetStatus(pw.ref)
436+
if err != nil {
437+
return 0, err
438+
}
439+
status.Offset = 0
440+
status.UpdatedAt = time.Now()
441+
pw.tracker.SetStatus(pw.ref, status)
442+
return 0, content.ErrReset
430443
}
431444
}
432445
status.Offset += int64(n)

0 commit comments

Comments
 (0)