From 1ccbff10a5d6f77a09ec59ee1e81380235a40806 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Gronowski?= Date: Wed, 22 Apr 2026 12:30:19 +0200 Subject: [PATCH] integration/container: Fix flaky TestContainerRestartWithCancelledRequest on Windows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The test relies on "trap ... TERM" to make the container ignore SIGTERM, ensuring the stop phase takes the full stopTimeout and giving the client time to cancel. On Windows, busybox-w32 doesn't support signal trapping, so the container may exit immediately on SIGTERM before the client cancels, making it impossible to reliably set up the intended scenario. This is consistent with other tests in the file: TestWaitBlocked skips on Windows entirely with the comment "Windows busybox does not support trap in this way", and TestContainerWaitForExit sets timeout=0 on Windows because "our process won't receive SIGTERM". Rather than skipping the test outright, retry up to 10 times on Windows so the test passes whenever the timing works out. Also bump the base restart timeout from 2s to 10s to provide headroom under CI load. Signed-off-by: Paweł Gronowski --- integration/container/restart_test.go | 42 ++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/integration/container/restart_test.go b/integration/container/restart_test.go index 2b67e055c6..f339fbeef3 100644 --- a/integration/container/restart_test.go +++ b/integration/container/restart_test.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "runtime" + "strconv" "testing" "time" @@ -227,10 +228,40 @@ func TestContainerWithAutoRemoveCanBeRestarted(t *testing.T) { // Regression test for https://github.com/moby/moby/discussions/46682 func TestContainerRestartWithCancelledRequest(t *testing.T) { ctx := setupTest(t) - apiClient := testEnv.APIClient() testutil.StartSpan(ctx, t) + // The test relies on "trap" to ignore SIGTERM so that the stop takes + // the full stopTimeout, giving the client time to cancel the request. + // On Windows, busybox-w32 doesn't support signal trapping (see + // https://github.com/rmyorston/busybox-w32/issues/303) so the + // container may exit immediately on SIGTERM, making the test + // scenario impossible to set up reliably. + // Allow multiple attempts on Windows so the test can pass when the timing + // happens to work out. + if runtime.GOOS == "windows" { + for retry := range 10 { + success := true + fail := func(t *testing.T) { + success = false + } + t.Run(strconv.Itoa(retry), func(t *testing.T) { + testContainerRestartWithCancelledRequest(ctx, t, fail) + }) + if success { + return + } + } + return + } + + testContainerRestartWithCancelledRequest(ctx, t, func(t *testing.T) { + t.Fatal("timeout waiting for restart event") + }) +} + +func testContainerRestartWithCancelledRequest(ctx context.Context, t *testing.T, fail func(t *testing.T)) { + apiClient := testEnv.APIClient() // Create a container that ignores SIGTERM and doesn't stop immediately, // giving us time to cancel the request. // @@ -268,11 +299,7 @@ func TestContainerRestartWithCancelledRequest(t *testing.T) { // // Note that we cannot use RestartCount for this, as that's only // used for restart-policies. - restartTimeout := 2 * time.Second - if runtime.GOOS == "windows" { - // hcs can sometimes take a long time to stop container. - restartTimeout = StopContainerWindowsPollTimeout - } + restartTimeout := 10 * time.Second select { case m := <-messages: assert.Check(t, is.Equal(m.Actor.ID, cID)) @@ -280,7 +307,8 @@ func TestContainerRestartWithCancelledRequest(t *testing.T) { case err := <-errs: assert.NilError(t, err) case <-time.After(restartTimeout): - t.Errorf("timeout waiting for restart event") + fail(t) + return } // Container should be restarted (running).