diff --git a/internal/oci/container.go b/internal/oci/container.go index 8fd14f3b13c..a1b8b6f47da 100644 --- a/internal/oci/container.go +++ b/internal/oci/container.go @@ -565,7 +565,10 @@ func (c *Container) Spoofed() bool { // If a stop is currently happening, it also sends the new timeout // along the stopTimeoutChan, allowing the in-progress stop // to stop faster, or ignore the new stop timeout. -func (c *Container) SetAsStopping(timeout int64) { +// In this case, it also returns true, signifying the caller doesn't have to +// Do any stop related cleanup, as the original caller (alreadyStopping=false) +// will do said cleanup. +func (c *Container) SetAsStopping(timeout int64) (alreadyStopping bool) { // First, need to check if the container is already stopping c.stopLock.Lock() defer c.stopLock.Unlock() @@ -579,12 +582,13 @@ func (c *Container) SetAsStopping(timeout int64) { case <-c.stoppedChan: // This case is to avoid waiting forever once another routine has finished. case <-c.stopStoppingChan: // This case is to avoid deadlocking with SetAsNotStopping. } - return + return true } // Regardless, set the container as actively stopping. c.stopping = true // And reset the stopStoppingChan c.stopStoppingChan = make(chan struct{}, 1) + return false } // SetAsNotStopping unsets the stopping field indicating to new callers that the container diff --git a/internal/oci/runtime_oci.go b/internal/oci/runtime_oci.go index 385928acd4f..32a06ff3893 100644 --- a/internal/oci/runtime_oci.go +++ b/internal/oci/runtime_oci.go @@ -699,7 +699,9 @@ func WaitContainerStop(ctx context.Context, c *Container, timeout time.Duration, // StopContainer stops a container. Timeout is given in seconds. func (r *runtimeOCI) StopContainer(ctx context.Context, c *Container, timeout int64) (retErr error) { - c.SetAsStopping(timeout) + if c.SetAsStopping(timeout) { + return nil + } defer func() { if retErr != nil { // Failed to stop, set stopping to false. diff --git a/test/ctr.bats b/test/ctr.bats index e135b3bcd1c..6bfd8a68f92 100644 --- a/test/ctr.bats +++ b/test/ctr.bats @@ -929,3 +929,16 @@ function check_oci_annotation() { crictl exec --sync "$ctr_id" sh -c "stat /run/.containerenv" } + +@test "ctr stop timeouts should decrease" { + start_crio + jq ' .command'='["/bin/sh", "-c", "trap \"echo hi\" INT; /bin/sleep 6000"]' \ + "$TESTDATA"/container_config.json > "$newconfig" + + ctr_id=$(crictl run "$newconfig" "$TESTDATA"/sandbox_config.json) + for i in {150..1}; do + crictl stop --timeout "$i" "$ctr_id" & + sleep .1 + done + crictl stop "$ctr_id" +}