mirror of
https://github.com/docker/compose.git
synced 2026-10-12 02:13:08 +00:00
fix: execRunPreStart bails out on a canceled context
Same interim narrowing as execStartContainer and execRunPostStart: the node hangs off the replica's create node, so when that create fails the pre_start hooks could still fire in the window before errgroup cancels the context. The structural fix stays tracked in #14081. Signed-off-by: Nicolas De Loof <[email protected]>
This commit is contained in:
committed by
Nicolas De loof
parent
51532f6d02
commit
f07cdafc3e
@@ -265,6 +265,15 @@ func (exec *planExecutor) execWaitCondition(ctx context.Context, op Operation) e
|
||||
// accepts — skips a second, redundant run of the hooks rather than erroring
|
||||
// on runners already consumed.
|
||||
func (exec *planExecutor) execRunPreStart(ctx context.Context, op Operation) error {
|
||||
// Same interim narrowing as execStartContainer's guard (see its
|
||||
// comment), not a full fix: this node hangs off the replica's create
|
||||
// node, whose done-channel closes before errgroup's ctx is canceled when
|
||||
// that create fails for a genuine reason, so a narrow window remains
|
||||
// where pre_start hooks could still run against the runner containers.
|
||||
if err := ctx.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
running, err := exec.compose.getContainers(ctx, exec.project.Name, oneOffExclude, false, op.Service.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -211,6 +211,26 @@ func TestExecRunPreStart_SkipsWhenReplicaAlreadyRunning(t *testing.T) {
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
|
||||
// TestExecRunPreStart_BailsOutWhenContextCanceled pins the same interim
|
||||
// narrowing execStartContainer and execRunPostStart carry: once ctx is
|
||||
// canceled (a sibling node failed), the node must neither touch the daemon
|
||||
// nor run hooks. No ContainerList expectation is registered: an unexpected
|
||||
// call fails the test.
|
||||
func TestExecRunPreStart_BailsOutWhenContextCanceled(t *testing.T) {
|
||||
svc, _, _ := newStartPhaseTestService(t)
|
||||
|
||||
service := types.ServiceConfig{
|
||||
Name: "web",
|
||||
PreStart: []types.PreStartHook{{ContainerSpec: types.ContainerSpec{Command: types.ShellCommand{"init"}}}},
|
||||
}
|
||||
ctx, cancel := context.WithCancel(t.Context())
|
||||
cancel()
|
||||
|
||||
exec := svc.newPlanExecutor(&types.Project{Name: "test"}, emptyObservedState("test"), nil)
|
||||
err := exec.execRunPreStart(ctx, Operation{Service: &service})
|
||||
assert.ErrorIs(t, err, context.Canceled)
|
||||
}
|
||||
|
||||
// TestExecRunPostStart_RunsHookAndStreamsToListener verifies that
|
||||
// execRunPostStart resolves the replica the start chain just brought up and
|
||||
// runs its post_start hooks, forwarding their output to the listener the
|
||||
|
||||
Reference in New Issue
Block a user