From 5f210e148801e33d186fbc4b3891abea11f2988d Mon Sep 17 00:00:00 2001 From: SAY-5 Date: Fri, 17 Apr 2026 14:40:50 -0700 Subject: [PATCH] fix(backend): close the ReadCloser returned by PullBlob in push pushIfNotExist pulled each blob's content from the source storage and then handed it to Blobs().Push wrapped in io.NopCloser. The NopCloser is there on purpose (Close on the distribution reader returns an error, see #50), but it also means the original ReadCloser from PullBlob was never closed on any path, leaking a file descriptor or HTTP body per blob. Add a `defer content.Close()` immediately after the nil-error check so the original reader is released on both success and error paths. The existing NopCloser wrapper still prevents Push from calling Close itself, so the workaround for #50 is preserved. Fixes #491 Signed-off-by: SAY-5 --- pkg/backend/push.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pkg/backend/push.go b/pkg/backend/push.go index 2674cee2..f2d05d80 100644 --- a/pkg/backend/push.go +++ b/pkg/backend/push.go @@ -176,6 +176,13 @@ func pushIfNotExist(ctx context.Context, pb *internalpb.ProgressBar, prompt stri if err != nil { return err } + // The ReadCloser returned by PullBlob was previously never closed on + // either path, leaking the underlying file descriptor (or HTTP body) + // for every blob we pushed. Close on the distribution implementation + // returns an error (#50), which is why we still wrap the reader with + // io.NopCloser below, but we DO need to close `content` ourselves. + // See #491. + defer content.Close() reader := pb.Add(prompt, desc.Digest.String(), desc.Size, content) // resolve issue: https://github.com/modelpack/modctl/issues/50