Skip to content

Commit 9d7641f

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 91a50f7 commit 9d7641f

File tree

1 file changed

+16
-3
lines changed

1 file changed

+16
-3
lines changed

core/remotes/docker/pusher.go

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

0 commit comments

Comments
 (0)