-
Notifications
You must be signed in to change notification settings - Fork 2.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
podman save use named pipe #7073
Conversation
@mtrmac I'm not sure if this works. Could you PTAL? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don’t quite think this works.
It’s probably worth splitting this into a separate function to keep the main flow fairly simple.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Things that should work:
- The base case of
podman save | cat > file
or something similar. podman save > /dev/full
should reliably fail; so shouldpodman save | read-one-byte-and-exit
.podman save | some-very-slow-consumer
should reliably receive all of the file (i.e. thesave
should not terminate until all of the data has been written).
See #7017 (comment) for a broad outline of what I think is necessary to make that work. (But, to be fair, I haven’t written and tested the code.)
9549ffd
to
cb9dbb5
Compare
The documentation example, are you suggesting this should fail?
|
I’m not quite sure what this refers to, but no, not in general. I was some ways to trigger failures that should be detected (note that |
@mtrmac PTAL |
6890d2c
to
f626be2
Compare
78eaf92
to
d2578ea
Compare
cmd/podman/images/save.go
Outdated
return err | ||
} | ||
defer func() { | ||
if err = cleanup(); err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAICS cleanup()
blocks until the pipe is opened and closed, which may never happen on some of the error paths, and this would just hang.
Maybe use context.Context
to terminate that wait, or just expose errc
and have this function inject a fallback “wait canceled” error that is then ignored in favor of the real cause.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mtrmac PTAL
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how to use context.Context to terminate?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The way the cleanup
function now returns a channel, a separate termination context might not be necessary:
func save(…) (finalErr error) {
succeeded := false
…
if /* use pipe */ {
pipePath, cleanup, err := setupPipe()
…
if cleanup != nil {
defer func() {
channel := cleanup()
if succeeded {
writeErr := <- channel
if writeErr != nil && finalErr == nil { finalErr = writeErr }
}
}
}
}
…
err := registry.ImageEngine().Save(context.Background(), args[0], tags, saveOpts)
if err == nil { succeeded = true }
return err
}
17c383f
to
0e50185
Compare
/approve |
cmd/podman/images/save.go
Outdated
@@ -6,6 +6,8 @@ import ( | |||
"strings" | |||
|
|||
"github.com/containers/podman/v2/libpod/define" | |||
"github.com/sirupsen/logrus" | |||
"golang.org/x/crypto/ssh/terminal" | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you eliminate this empty line.
cmd/podman/images/save.go
Outdated
} | ||
defer func() { | ||
errc := cleanup() | ||
if err := <-errc; err != nil && err.Error() != "wait canceled" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you make "wait canceled" into a constant error, rather then a string. Call it Success.
cmd/podman/images/utils_linux.go
Outdated
"io/ioutil" | ||
"os" | ||
"path/filepath" | ||
"syscall" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use golang.org/x/sys/unix instead of syscall
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: QiWang19, rhatdan The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
Can you add some tests? |
@mtrmac PTAL, will this avoid the hangs? |
The command needs test is |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don’t think this works. Test by replacing the parse.ValidateFileName
call with a forced err = "this failed"
— the command should not hang, it should remove the temporary directory, and it should return the “this failed” error string.
cmd/podman/images/utils_linux.go
Outdated
return | ||
} | ||
fpipe.Close() | ||
errc <- errWaitCancel |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this reporting any error at all when the goroutine has succeeded?
podman/test/system/015-help.bats Line 19 in 43f2771
In Go, It might be possible to use |
Without going into too much gory detail... it's not.The BATS That cannot work for this PR because the critical point is that the |
Thanks! |
a8e9594
to
2937453
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
(I’ll leave the aesthetic nits and tests, if any, up to Podman experts.)
|
||
// setupPipe() for fixing https://github.com/containers/podman/issues/7017 | ||
// uses named pipe since containers/image EvalSymlinks fails with /dev/stdout | ||
func setupPipe() (string, func() <-chan error, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Non-blocking: The semantics of the cleanup callback is now complex enough that it might be worth documenting. (OTOH it’s not that much code and it has a single user.)
podman save uses named pipe as output path, not directly using /dev/stdout. fix containers#7017 Signed-off-by: Qi Wang <[email protected]>
/lgtm |
podman save uses named pipe as output path, not directly using /dev/stdout.
fix #7017
Signed-off-by: Qi Wang [email protected]