mirror of
https://github.com/containers/podman.git
synced 2025-06-21 01:19:15 +08:00
Merge pull request #20394 from giuseppe/cleanup-exec-session-on-errors
exec: do not leak session IDs on errors
This commit is contained in:
@ -759,11 +759,19 @@ func (c *Container) Exec(config *ExecConfig, streams *define.AttachStreams, resi
|
|||||||
// Exec emulates the old Libpod exec API, providing a single call to create,
|
// Exec emulates the old Libpod exec API, providing a single call to create,
|
||||||
// run, and remove an exec session. Returns exit code and error. Exit code is
|
// run, and remove an exec session. Returns exit code and error. Exit code is
|
||||||
// not guaranteed to be set sanely if error is not nil.
|
// not guaranteed to be set sanely if error is not nil.
|
||||||
func (c *Container) exec(config *ExecConfig, streams *define.AttachStreams, resizeChan <-chan resize.TerminalSize, isHealthcheck bool) (int, error) {
|
func (c *Container) exec(config *ExecConfig, streams *define.AttachStreams, resizeChan <-chan resize.TerminalSize, isHealthcheck bool) (exitCode int, retErr error) {
|
||||||
sessionID, err := c.ExecCreate(config)
|
sessionID, err := c.ExecCreate(config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return -1, err
|
return -1, err
|
||||||
}
|
}
|
||||||
|
defer func() {
|
||||||
|
if err := c.ExecRemove(sessionID, false); err != nil {
|
||||||
|
if retErr == nil && !errors.Is(err, define.ErrNoSuchExecSession) {
|
||||||
|
exitCode = -1
|
||||||
|
retErr = err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
// Start resizing if we have a resize channel.
|
// Start resizing if we have a resize channel.
|
||||||
// This goroutine may likely leak, given that we cannot close it here.
|
// This goroutine may likely leak, given that we cannot close it here.
|
||||||
@ -813,15 +821,7 @@ func (c *Container) exec(config *ExecConfig, streams *define.AttachStreams, resi
|
|||||||
}
|
}
|
||||||
return -1, err
|
return -1, err
|
||||||
}
|
}
|
||||||
exitCode := session.ExitCode
|
return session.ExitCode, nil
|
||||||
if err := c.ExecRemove(sessionID, false); err != nil {
|
|
||||||
if errors.Is(err, define.ErrNoSuchExecSession) {
|
|
||||||
return exitCode, nil
|
|
||||||
}
|
|
||||||
return -1, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return exitCode, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// cleanupExecBundle cleanups an exec session after its done
|
// cleanupExecBundle cleanups an exec session after its done
|
||||||
|
@ -904,6 +904,7 @@ func (ic *ContainerEngine) ContainerExecDetached(ctx context.Context, nameOrID s
|
|||||||
|
|
||||||
// TODO: we should try and retrieve exit code if this fails.
|
// TODO: we should try and retrieve exit code if this fails.
|
||||||
if err := ctr.ExecStart(id); err != nil {
|
if err := ctr.ExecStart(id); err != nil {
|
||||||
|
_ = ctr.ExecRemove(id, true)
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
return id, nil
|
return id, nil
|
||||||
|
@ -166,4 +166,17 @@ load helpers
|
|||||||
run_podman rm -f -t0 $cid
|
run_podman rm -f -t0 $cid
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@test "podman exec - does not leak session IDs on invalid command" {
|
||||||
|
run_podman run -d $IMAGE top
|
||||||
|
cid="$output"
|
||||||
|
|
||||||
|
for i in {1..3}; do
|
||||||
|
run_podman 127 exec $cid blahblah
|
||||||
|
run_podman 125 exec -d $cid blahblah
|
||||||
|
done
|
||||||
|
|
||||||
|
run_podman inspect --format "{{len .ExecIDs}}" $cid
|
||||||
|
assert "$output" = "0" ".ExecIDs must be empty"
|
||||||
|
}
|
||||||
|
|
||||||
# vim: filetype=sh
|
# vim: filetype=sh
|
||||||
|
@ -339,11 +339,18 @@ function run_podman() {
|
|||||||
# Remember command args, for possible use in later diagnostic messages
|
# Remember command args, for possible use in later diagnostic messages
|
||||||
MOST_RECENT_PODMAN_COMMAND="podman $*"
|
MOST_RECENT_PODMAN_COMMAND="podman $*"
|
||||||
|
|
||||||
|
# BATS treats 127 as a special case, so we need to silence it when 127 is the
|
||||||
|
# expected rc: https://bats-core.readthedocs.io/en/stable/warnings/BW01.html
|
||||||
|
silence127=""
|
||||||
|
if [ $expected_rc -eq 127 ]; then
|
||||||
|
silence127="-127"
|
||||||
|
fi
|
||||||
|
|
||||||
# stdout is only emitted upon error; this printf is to help in debugging
|
# stdout is only emitted upon error; this printf is to help in debugging
|
||||||
printf "\n%s %s %s %s\n" "$(timestamp)" "$_LOG_PROMPT" "$PODMAN" "$*"
|
printf "\n%s %s %s %s\n" "$(timestamp)" "$_LOG_PROMPT" "$PODMAN" "$*"
|
||||||
# BATS hangs if a subprocess remains and keeps FD 3 open; this happens
|
# BATS hangs if a subprocess remains and keeps FD 3 open; this happens
|
||||||
# if podman crashes unexpectedly without cleaning up subprocesses.
|
# if podman crashes unexpectedly without cleaning up subprocesses.
|
||||||
run timeout --foreground -v --kill=10 $PODMAN_TIMEOUT $PODMAN $_PODMAN_TEST_OPTS "$@" 3>/dev/null
|
run $silence127 timeout --foreground -v --kill=10 $PODMAN_TIMEOUT $PODMAN $_PODMAN_TEST_OPTS "$@" 3>/dev/null
|
||||||
# without "quotes", multiple lines are glommed together into one
|
# without "quotes", multiple lines are glommed together into one
|
||||||
if [ -n "$output" ]; then
|
if [ -n "$output" ]; then
|
||||||
echo "$(timestamp) $output"
|
echo "$(timestamp) $output"
|
||||||
|
Reference in New Issue
Block a user