summaryrefslogtreecommitdiff
path: root/pkg/api
diff options
context:
space:
mode:
authorMatej Vasek <mvasek@redhat.com>2021-05-07 22:35:20 +0200
committerMatej Vasek <mvasek@redhat.com>2021-05-10 13:40:06 +0200
commit66e38ca55d9a0079eb7d317b5a70c2623fc90d20 (patch)
tree3ea45c42923ca1954d9e8e01297c75114a0f4d4c /pkg/api
parent0ce6a65b3961465593470c3457d75b0a846c8d98 (diff)
downloadpodman-66e38ca55d9a0079eb7d317b5a70c2623fc90d20.tar.gz
podman-66e38ca55d9a0079eb7d317b5a70c2623fc90d20.tar.bz2
podman-66e38ca55d9a0079eb7d317b5a70c2623fc90d20.zip
fix: improved "containers/{name}/wait" endpoint
Using event API to detect changes to container instead of polling. Polling was unreliable, sometime change of a state might have been missed. Signed-off-by: Matej Vasek <mvasek@redhat.com>
Diffstat (limited to 'pkg/api')
-rw-r--r--pkg/api/handlers/utils/containers.go35
1 files changed, 28 insertions, 7 deletions
diff --git a/pkg/api/handlers/utils/containers.go b/pkg/api/handlers/utils/containers.go
index c4c9cc2ea..6c708f74e 100644
--- a/pkg/api/handlers/utils/containers.go
+++ b/pkg/api/handlers/utils/containers.go
@@ -7,6 +7,7 @@ import (
"strconv"
"time"
+ "github.com/containers/podman/v3/libpod/events"
"github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/domain/infra/abi"
@@ -175,7 +176,7 @@ func waitDockerCondition(ctx context.Context, containerName string, interval tim
var code int32
switch dockerCondition {
case "next-exit":
- code, err = waitNextExit(containerWait)
+ code, err = waitNextExit(ctx, containerName)
case "removed":
code, err = waitRemoved(containerWait)
case "not-running", "":
@@ -202,12 +203,32 @@ func waitRemoved(ctrWait containerWaitFn) (int32, error) {
return code, err
}
-func waitNextExit(ctrWait containerWaitFn) (int32, error) {
- _, err := ctrWait(define.ContainerStateRunning)
- if err != nil {
- return -1, err
- }
- return ctrWait(notRunningStates...)
+func waitNextExit(ctx context.Context, containerName string) (int32, error) {
+ runtime := ctx.Value("runtime").(*libpod.Runtime)
+ containerEngine := &abi.ContainerEngine{Libpod: runtime}
+ eventChannel := make(chan *events.Event)
+ errChannel := make(chan error)
+ opts := entities.EventsOptions{
+ EventChan: eventChannel,
+ Filter: []string{"event=died", fmt.Sprintf("container=%s", containerName)},
+ Stream: true,
+ }
+
+ // ctx is used to cancel event watching goroutine
+ ctx, cancel := context.WithCancel(ctx)
+ defer cancel()
+ go func() {
+ errChannel <- containerEngine.Events(ctx, opts)
+ }()
+
+ evt, ok := <-eventChannel
+ if ok {
+ return int32(evt.ContainerExitCode), nil
+ }
+ // if ok == false then containerEngine.Events() has exited
+ // it may happen if request was canceled (e.g. client closed connection prematurely) or
+ // the server is in process of shutting down
+ return -1, <-errChannel
}
func waitNotRunning(ctrWait containerWaitFn) (int32, error) {