Skip to content
This repository was archived by the owner on Jul 18, 2025. It is now read-only.

Commit d26c9ad

Browse files
author
Ulysses Souza
committed
Create a global variable to hold output file
With a function scoped `os.File`, next time the GC passes the instance is collected, calling the finalizer and triggering the invalidation of the FD, that cannot be used anymore. Signed-off-by: Ulysses Souza <[email protected]>
1 parent e3a9aed commit d26c9ad

File tree

1 file changed

+28
-7
lines changed

1 file changed

+28
-7
lines changed

internal/commands/build/build.go

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"github.com/docker/cli/cli"
2424
"github.com/docker/cli/cli/command"
2525
compose "github.com/docker/cli/cli/compose/types"
26+
"github.com/docker/cli/cli/streams"
2627
"github.com/docker/cnab-to-oci/remotes"
2728
"github.com/docker/distribution/reference"
2829
"github.com/moby/buildkit/client"
@@ -75,6 +76,30 @@ func Cmd(dockerCli command.Cli) *cobra.Command {
7576
return cmd
7677
}
7778

79+
// FIXME: DO NOT SET THIS VARIABLE DIRECTLY! Use `getOutputFile`
80+
// This global var prevents the file to be garbage collected and by that invalidated
81+
// A an alternative fix for this would be writing the output to a bytes buffer and flushing to stdout.
82+
// The impossibility here is that os.File is not an interface that a buffer can implement.
83+
// Maybe `progress.NewPrinter` should implement an "os.File-like" interface just for its needs.
84+
// See https://github.com/golang/go/issues/14106
85+
var _outputFile *os.File
86+
87+
func getOutputFile(realOut *streams.Out, quiet bool) (*os.File, error) {
88+
if _outputFile != nil {
89+
return _outputFile, nil
90+
}
91+
if quiet {
92+
var err error
93+
_outputFile, err = os.Create(os.DevNull)
94+
if err != nil {
95+
return nil, err
96+
}
97+
return _outputFile, nil
98+
}
99+
_outputFile = os.NewFile(realOut.FD(), os.Stdout.Name())
100+
return _outputFile, nil
101+
}
102+
78103
func runBuild(dockerCli command.Cli, contextPath string, opt buildOptions) error {
79104
err := checkMinimalEngineVersion(dockerCli)
80105
if err != nil {
@@ -160,13 +185,9 @@ func buildImageUsingBuildx(app *types.App, contextPath string, opt buildOptions,
160185
},
161186
}
162187

163-
var out *os.File
164-
if opt.quiet {
165-
if out, err = os.Create(os.DevNull); err != nil {
166-
return nil, err
167-
}
168-
} else {
169-
out = os.NewFile(dockerCli.Out().FD(), "/dev/stdout")
188+
out, err := getOutputFile(dockerCli.Out(), opt.quiet)
189+
if err != nil {
190+
return nil, err
170191
}
171192

172193
pw := progress.NewPrinter(ctx, out, opt.progress)

0 commit comments

Comments
 (0)