mirror of
https://github.com/containerd/containerd.git
synced 2026-11-06 13:27:16 +00:00
The pusher creates the upload request body as an io.Pipe. request.do attaches the pipe reader to the request before calling Authorize. If Authorize fails, do returns before client.Do, so the reader is never handed to the HTTP client, which would have closed it, and nothing else closes it. A concurrent pushWriter.Write then blocks forever in pipe.Write. It only reads the error reported by the request goroutine after the pipe is closed, and it takes no context, so cancelling the caller does not help. Callers such as content.Copy never return, and anything they hold, for example a concurrency slot, is never released. Close the body when authorization fails so the blocked Write returns the authorization error. Transient errors keep going through the existing retry and content.ErrReset handling. Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>