Browse code

api/types/container: move StateStatus, NewStateStatus internal again

These types used to be internal to the container package, but were
moved to the API in 100102108b2f096cd43165e4522a6314bc16f07c.

However, the `StateStatus` type is only used internally; it's used
as an intermediate type because [`container.State`] contains a sync.Mutex
field which would make copying it unsafe (see [moby@2998945]).

This moves the type and re-introduces an internal type
in the original location, effectively reverting
100102108b2f096cd43165e4522a6314bc16f07c

[`container.State`]: https://github.com/moby/moby/blob/19e79906cb347ab12deaade16bf9d82c41d777c4/container/state.go#L15-L23
[moby@2998945]: https://github.com/moby/moby/commit/2998945a54577e24a6414d576bc861e58fa87359

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>

Sebastiaan van Stijn authored on 2025/07/24 04:30:08
Showing 9 changed files
... ...
@@ -34,31 +34,3 @@ func ValidateContainerState(s ContainerState) error {
34 34
 		return errInvalidParameter{error: fmt.Errorf("invalid value for state (%s): must be one of %s", s, strings.Join(validStates, ", "))}
35 35
 	}
36 36
 }
37
-
38
-// StateStatus is used to return container wait results.
39
-// Implements exec.ExitCode interface.
40
-// This type is needed as State include a sync.Mutex field which make
41
-// copying it unsafe.
42
-type StateStatus struct {
43
-	exitCode int
44
-	err      error
45
-}
46
-
47
-// ExitCode returns current exitcode for the state.
48
-func (s StateStatus) ExitCode() int {
49
-	return s.exitCode
50
-}
51
-
52
-// Err returns current error for the state. Returns nil if the container had
53
-// exited on its own.
54
-func (s StateStatus) Err() error {
55
-	return s.err
56
-}
57
-
58
-// NewStateStatus returns a new StateStatus with the given exit code and error.
59
-func NewStateStatus(exitCode int, err error) StateStatus {
60
-	return StateStatus{
61
-		exitCode: exitCode,
62
-		err:      err,
63
-	}
64
-}
... ...
@@ -8,6 +8,7 @@ import (
8 8
 	"context"
9 9
 	"io"
10 10
 
11
+	containerpkg "github.com/docker/docker/daemon/container"
11 12
 	"github.com/docker/docker/daemon/internal/image"
12 13
 	"github.com/docker/docker/daemon/internal/layer"
13 14
 	"github.com/docker/docker/daemon/server/backend"
... ...
@@ -65,7 +66,7 @@ type ExecBackend interface {
65 65
 	// ContainerStart starts a new container
66 66
 	ContainerStart(ctx context.Context, containerID string, checkpoint string, checkpointDir string) error
67 67
 	// ContainerWait stops processing until the given container is stopped.
68
-	ContainerWait(ctx context.Context, name string, condition container.WaitCondition) (<-chan container.StateStatus, error)
68
+	ContainerWait(ctx context.Context, name string, condition container.WaitCondition) (<-chan containerpkg.StateStatus, error)
69 69
 }
70 70
 
71 71
 // Result is the output produced by a Builder
... ...
@@ -7,6 +7,7 @@ import (
7 7
 	"runtime"
8 8
 
9 9
 	"github.com/docker/docker/daemon/builder"
10
+	containerpkg "github.com/docker/docker/daemon/container"
10 11
 	"github.com/docker/docker/daemon/internal/image"
11 12
 	"github.com/docker/docker/daemon/internal/layer"
12 13
 	"github.com/docker/docker/daemon/server/backend"
... ...
@@ -49,7 +50,7 @@ func (m *MockBackend) ContainerStart(ctx context.Context, containerID string, ch
49 49
 	return nil
50 50
 }
51 51
 
52
-func (m *MockBackend) ContainerWait(ctx context.Context, containerID string, condition container.WaitCondition) (<-chan container.StateStatus, error) {
52
+func (m *MockBackend) ContainerWait(ctx context.Context, containerID string, condition container.WaitCondition) (<-chan containerpkg.StateStatus, error) {
53 53
 	return nil, nil
54 54
 }
55 55
 
... ...
@@ -8,6 +8,7 @@ import (
8 8
 	"github.com/distribution/reference"
9 9
 	"github.com/docker/distribution"
10 10
 	clustertypes "github.com/docker/docker/daemon/cluster/provider"
11
+	containerpkg "github.com/docker/docker/daemon/container"
11 12
 	"github.com/docker/docker/daemon/internal/image"
12 13
 	"github.com/docker/docker/daemon/libnetwork"
13 14
 	"github.com/docker/docker/daemon/libnetwork/cluster"
... ...
@@ -44,7 +45,7 @@ type Backend interface {
44 44
 	DeactivateContainerServiceBinding(containerName string) error
45 45
 	UpdateContainerServiceConfig(containerName string, serviceConfig *clustertypes.ServiceConfig) error
46 46
 	ContainerInspect(ctx context.Context, name string, options backend.ContainerInspectOptions) (*container.InspectResponse, error)
47
-	ContainerWait(ctx context.Context, name string, condition container.WaitCondition) (<-chan container.StateStatus, error)
47
+	ContainerWait(ctx context.Context, name string, condition container.WaitCondition) (<-chan containerpkg.StateStatus, error)
48 48
 	ContainerRm(name string, config *backend.ContainerRmConfig) error
49 49
 	ContainerKill(name string, sig string) error
50 50
 	SetContainerDependencyStore(name string, store exec.DependencyGetter) error
... ...
@@ -16,6 +16,7 @@ import (
16 16
 	"github.com/docker/docker/daemon"
17 17
 	"github.com/docker/docker/daemon/cluster/convert"
18 18
 	executorpkg "github.com/docker/docker/daemon/cluster/executor"
19
+	containerpkg "github.com/docker/docker/daemon/container"
19 20
 	"github.com/docker/docker/daemon/libnetwork"
20 21
 	networkSettings "github.com/docker/docker/daemon/network"
21 22
 	"github.com/docker/docker/daemon/server/backend"
... ...
@@ -415,7 +416,7 @@ func (c *containerAdapter) events(ctx context.Context) <-chan events.Message {
415 415
 	return eventsq
416 416
 }
417 417
 
418
-func (c *containerAdapter) wait(ctx context.Context) (<-chan containertypes.StateStatus, error) {
418
+func (c *containerAdapter) wait(ctx context.Context) (<-chan containerpkg.StateStatus, error) {
419 419
 	return c.backend.ContainerWait(ctx, c.container.nameOrID(), containertypes.WaitConditionNotRunning)
420 420
 }
421 421
 
... ...
@@ -46,8 +46,8 @@ type State struct {
46 46
 	Health            *Health
47 47
 	Removed           bool `json:"-"`
48 48
 
49
-	stopWaiters       []chan<- container.StateStatus
50
-	removeOnlyWaiters []chan<- container.StateStatus
49
+	stopWaiters       []chan<- StateStatus
50
+	removeOnlyWaiters []chan<- StateStatus
51 51
 
52 52
 	// The libcontainerd reference fields are unexported to force consumers
53 53
 	// to access them through the getter methods with multi-valued returns
... ...
@@ -58,6 +58,26 @@ type State struct {
58 58
 	task libcontainerdtypes.Task
59 59
 }
60 60
 
61
+// StateStatus is used to return container wait results.
62
+// Implements exec.ExitCode interface.
63
+// This type is needed as State include a sync.Mutex field which make
64
+// copying it unsafe.
65
+type StateStatus struct {
66
+	exitCode int
67
+	err      error
68
+}
69
+
70
+// ExitCode returns current exitcode for the state.
71
+func (s StateStatus) ExitCode() int {
72
+	return s.exitCode
73
+}
74
+
75
+// Err returns current error for the state. Returns nil if the container had
76
+// exited on its own.
77
+func (s StateStatus) Err() error {
78
+	return s.err
79
+}
80
+
61 81
 // NewState creates a default state object.
62 82
 func NewState() *State {
63 83
 	return &State{}
... ...
@@ -138,20 +158,23 @@ func (s *State) StateString() container.ContainerState {
138 138
 // be nil and its ExitCode() method will return the container's exit code,
139 139
 // otherwise, the results Err() method will return an error indicating why the
140 140
 // wait operation failed.
141
-func (s *State) Wait(ctx context.Context, condition container.WaitCondition) <-chan container.StateStatus {
141
+func (s *State) Wait(ctx context.Context, condition container.WaitCondition) <-chan StateStatus {
142 142
 	s.Lock()
143 143
 	defer s.Unlock()
144 144
 
145 145
 	// Buffer so we can put status and finish even nobody receives it.
146
-	resultC := make(chan container.StateStatus, 1)
146
+	resultC := make(chan StateStatus, 1)
147 147
 
148 148
 	if s.conditionAlreadyMet(condition) {
149
-		resultC <- container.NewStateStatus(s.ExitCode(), s.Err())
149
+		resultC <- StateStatus{
150
+			exitCode: s.ExitCodeValue,
151
+			err:      s.Err(),
152
+		}
150 153
 
151 154
 		return resultC
152 155
 	}
153 156
 
154
-	waitC := make(chan container.StateStatus, 1)
157
+	waitC := make(chan StateStatus, 1)
155 158
 
156 159
 	// Removal wakes up both removeOnlyWaiters and stopWaiters
157 160
 	// Container could be removed while still in "created" state
... ...
@@ -166,8 +189,10 @@ func (s *State) Wait(ctx context.Context, condition container.WaitCondition) <-c
166 166
 		select {
167 167
 		case <-ctx.Done():
168 168
 			// Context timeout or cancellation.
169
-			resultC <- container.NewStateStatus(-1, ctx.Err())
170
-
169
+			resultC <- StateStatus{
170
+				exitCode: -1,
171
+				err:      ctx.Err(),
172
+			}
171 173
 			return
172 174
 		case status := <-waitC:
173 175
 			resultC <- status
... ...
@@ -397,8 +422,11 @@ func (s *State) Err() error {
397 397
 	return nil
398 398
 }
399 399
 
400
-func (s *State) notifyAndClear(waiters *[]chan<- container.StateStatus) {
401
-	result := container.NewStateStatus(s.ExitCodeValue, s.Err())
400
+func (s *State) notifyAndClear(waiters *[]chan<- StateStatus) {
401
+	result := StateStatus{
402
+		exitCode: s.ExitCodeValue,
403
+		err:      s.Err(),
404
+	}
402 405
 
403 406
 	for _, c := range *waiters {
404 407
 		c <- result
... ...
@@ -4,6 +4,7 @@ import (
4 4
 	"context"
5 5
 	"io"
6 6
 
7
+	containerpkg "github.com/docker/docker/daemon/container"
7 8
 	"github.com/docker/docker/daemon/server/backend"
8 9
 	"github.com/moby/go-archive"
9 10
 	"github.com/moby/moby/api/types/container"
... ...
@@ -40,7 +41,7 @@ type stateBackend interface {
40 40
 	ContainerStop(ctx context.Context, name string, options container.StopOptions) error
41 41
 	ContainerUnpause(name string) error
42 42
 	ContainerUpdate(name string, hostConfig *container.HostConfig) (container.UpdateResponse, error)
43
-	ContainerWait(ctx context.Context, name string, condition container.WaitCondition) (<-chan container.StateStatus, error)
43
+	ContainerWait(ctx context.Context, name string, condition container.WaitCondition) (<-chan containerpkg.StateStatus, error)
44 44
 }
45 45
 
46 46
 // monitorBackend includes functions to implement to provide containers monitoring functionality.
... ...
@@ -3,6 +3,7 @@ package daemon
3 3
 import (
4 4
 	"context"
5 5
 
6
+	"github.com/docker/docker/daemon/container"
6 7
 	containertypes "github.com/moby/moby/api/types/container"
7 8
 )
8 9
 
... ...
@@ -13,7 +14,7 @@ import (
13 13
 // condition is met or if an error occurs waiting for the container (such as a
14 14
 // context timeout or cancellation). On a successful wait, the exit code of the
15 15
 // container is returned in the status with a non-nil Err() value.
16
-func (daemon *Daemon) ContainerWait(ctx context.Context, name string, condition containertypes.WaitCondition) (<-chan containertypes.StateStatus, error) {
16
+func (daemon *Daemon) ContainerWait(ctx context.Context, name string, condition containertypes.WaitCondition) (<-chan container.StateStatus, error) {
17 17
 	cntr, err := daemon.GetContainer(name)
18 18
 	if err != nil {
19 19
 		return nil, err
... ...
@@ -34,31 +34,3 @@ func ValidateContainerState(s ContainerState) error {
34 34
 		return errInvalidParameter{error: fmt.Errorf("invalid value for state (%s): must be one of %s", s, strings.Join(validStates, ", "))}
35 35
 	}
36 36
 }
37
-
38
-// StateStatus is used to return container wait results.
39
-// Implements exec.ExitCode interface.
40
-// This type is needed as State include a sync.Mutex field which make
41
-// copying it unsafe.
42
-type StateStatus struct {
43
-	exitCode int
44
-	err      error
45
-}
46
-
47
-// ExitCode returns current exitcode for the state.
48
-func (s StateStatus) ExitCode() int {
49
-	return s.exitCode
50
-}
51
-
52
-// Err returns current error for the state. Returns nil if the container had
53
-// exited on its own.
54
-func (s StateStatus) Err() error {
55
-	return s.err
56
-}
57
-
58
-// NewStateStatus returns a new StateStatus with the given exit code and error.
59
-func NewStateStatus(exitCode int, err error) StateStatus {
60
-	return StateStatus{
61
-		exitCode: exitCode,
62
-		err:      err,
63
-	}
64
-}