libpod API: make wait endpoint better against rm races

In the common scenario of podman-remote run --rm the API is required to
attach + start + wait to get exit code. This has the problem that the
wait call races against the container removal from the cleanup process
so it may not get the exit code back. However we keep the exit code
around for longer than the container so  we can just look it up in the
endpoint. Of course this only works when we get a full id as param but
podman-remote will do that.

Signed-off-by: Paul Holzinger <pholzing@redhat.com>
This commit is contained in:
Paul Holzinger 2024-10-08 17:52:22 +02:00
parent 3215d5124f
commit b3829a2932
No known key found for this signature in database
GPG Key ID: EB145DD938A3CAF2
2 changed files with 15 additions and 0 deletions

View File

@ -1393,3 +1393,7 @@ func (r *Runtime) SystemCheck(ctx context.Context, options entities.SystemCheckO
return report, err return report, err
} }
func (r *Runtime) GetContainerExitCode(id string) (int32, error) {
return r.state.GetContainerExitCode(id)
}

View File

@ -130,6 +130,17 @@ func WaitContainerLibpod(w http.ResponseWriter, r *http.Request) {
reports, err := containerEngine.ContainerWait(r.Context(), []string{name}, opts) reports, err := containerEngine.ContainerWait(r.Context(), []string{name}, opts)
if err != nil { if err != nil {
if errors.Is(err, define.ErrNoSuchCtr) { if errors.Is(err, define.ErrNoSuchCtr) {
// Special case: In the common scenario of podman-remote run --rm
// the API is required to attach + start + wait to get exit code.
// This has the problem that the wait call races against the container
// removal from the cleanup process so it may not get the exit code back.
// However we keep the exit code around for longer than the container so
// we can just look it up here. Of course this only works when we get a
// full id as param but podman-remote will do that
if code, err := runtime.GetContainerExitCode(name); err == nil {
WriteResponse(w, http.StatusOK, strconv.Itoa(int(code)))
return
}
ContainerNotFound(w, name, err) ContainerNotFound(w, name, err)
return return
} }