diff --git a/libpod/runtime.go b/libpod/runtime.go index 1aea7b4fe6..1daf2855b2 100644 --- a/libpod/runtime.go +++ b/libpod/runtime.go @@ -1393,3 +1393,7 @@ func (r *Runtime) SystemCheck(ctx context.Context, options entities.SystemCheckO return report, err } + +func (r *Runtime) GetContainerExitCode(id string) (int32, error) { + return r.state.GetContainerExitCode(id) +} diff --git a/pkg/api/handlers/utils/containers.go b/pkg/api/handlers/utils/containers.go index 62af4b45d1..07f8ca7f2f 100644 --- a/pkg/api/handlers/utils/containers.go +++ b/pkg/api/handlers/utils/containers.go @@ -130,6 +130,17 @@ func WaitContainerLibpod(w http.ResponseWriter, r *http.Request) { reports, err := containerEngine.ContainerWait(r.Context(), []string{name}, opts) if err != nil { 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) return }