Allow running exec with no attach streams requested

This is a small Docker compat fix with the API exec endpoints.
With Docker, sending a bare Exec Create (command only, nothing
else set) and then an Exec Start without Detach set performs
a detached exec. With Podman, we threw an error that at least one
stream must be attached to. Fix is trivial; look up the session
before start, check the config for attach streams, and force
detach on if none are set.

Signed-off-by: Matthew Heon <matthew.heon@pm.me>
This commit is contained in:
Matthew Heon 2026-05-11 15:07:47 -04:00 • committed by Matt Heon
parent dde83193d1
commit 7487854f10
3 changed files with 38 additions and 1 deletions

View file

@ -175,6 +175,19 @@ func ExecStartHandler(w http.ResponseWriter, r *http.Request) {
return
}
// If no streams were requested for attach, detach is implied
if !bodyParams.Detach {
execSession, err := sessionCtr.ExecSession(sessionID)
if err != nil {
utils.InternalServerError(w, err)
return
}
if !execSession.Config.AttachStderr && !execSession.Config.AttachStdout && !execSession.Config.AttachStdin {
bodyParams.Detach = true
}
}
if bodyParams.Detach {
// If we are detaching, we do NOT want to hijack.
// Instead, we perform a detached start, and return 200 if

View file

@ -273,7 +273,8 @@ func (s *APIServer) registerExecHandlers(r *mux.Router) error {
// properties:
// Detach:
// type: boolean
// description: Detach from the command.
// description: |
// "Detach from the command. Detach defaults to true if no attach streams were specified when the session was created (IE AttachStdin, AttachStdout, AttachStderr are all false)."
// Tty:
// type: boolean
// description: Allocate a pseudo-TTY.

View file

@ -988,6 +988,29 @@ t POST libpod/containers/$cid/update \
t DELETE containers/$cid 204
# Verify that exec session with no attach streams specified can be started
CTRNAME=exectest
podman run -d --name $CTRNAME $IMAGE top
echo '{ "Cmd":["sh", "-c", "echo hello > /tmp/testfile"]}' >${TMPD}/exec_empty.json
t POST "containers/$CTRNAME/exec" ${TMPD}/exec_empty.json 201 .Id~[0-9a-f]\\{64\\}
eid=$(jq -r '.Id' <<<"$output")
t POST exec/$eid/start 200
# Need to wait for the exec to actually run, given it's detached.
# Use $PODMAN_BIN --root directly instead of the podman wrapper, since we
# need to capture the command output.
TRIES=5
while [[ $TRIES -gt 0 ]]; do
exec_out=$($PODMAN_BIN --root $WORKDIR/server_root exec $CTRNAME ls /tmp/testfile 2>/dev/null)
if [[ "$exec_out" = "/tmp/testfile" ]]; then
break
fi
sleep 1
TRIES=$((TRIES - 1))
done
out=$($PODMAN_BIN --root $WORKDIR/server_root exec $CTRNAME cat /tmp/testfile 2>/dev/null)
is "$out" "hello"
podman rm -f $CTRNAME
rm -rf $TMPD
podman container rm -fa