@@ -85,34 +85,23 @@ func (c *Container) initUnlocked(ctx context.Context, recursive bool) error {
85
85
// Start requires that all dependency containers (e.g. pod infra containers) are
86
86
// running before starting the container. The recursive parameter, if set, will start all
87
87
// dependencies before starting this container.
88
- func (c * Container ) Start (ctx context.Context , recursive bool ) (finalErr error ) {
89
- if ! c .batched {
90
- c .lock .Lock ()
91
- defer c .lock .Unlock ()
92
-
93
- // defer's are executed LIFO so we are locked here
94
- // as long as we call this after the defer unlock()
95
- defer func () {
96
- if finalErr != nil {
97
- if err := saveContainerError (c , finalErr ); err != nil {
98
- logrus .Debug (err )
99
- }
100
- }
101
- }()
102
-
103
- if err := c .syncContainer (); err != nil {
104
- return err
88
+ func (c * Container ) Start (ctx context.Context , recursive bool ) error {
89
+ // Have to lock the pod the container is a part of.
90
+ // This prevents running `podman start` at the same time a
91
+ // `podman pod stop` is running, which could lead to weird races.
92
+ // Pod locks come before container locks, so do this first.
93
+ if c .config .Pod != "" {
94
+ // If we get an error, the pod was probably removed.
95
+ // So we get an expected ErrCtrRemoved instead of ErrPodRemoved,
96
+ // just ignore this and move on to syncing the container.
97
+ pod , _ := c .runtime .state .Pod (c .config .Pod )
98
+ if pod != nil {
99
+ pod .lock .Lock ()
100
+ defer pod .lock .Unlock ()
105
101
}
106
102
}
107
- if err := c .prepareToStart (ctx , recursive ); err != nil {
108
- return err
109
- }
110
103
111
- // Start the container
112
- if err := c .start (); err != nil {
113
- return err
114
- }
115
- return c .waitForHealthy (ctx )
104
+ return c .startNoPodLock (ctx , recursive )
116
105
}
117
106
118
107
// Update updates the given container.
@@ -294,6 +283,21 @@ func (c *Container) Stop() error {
294
283
// manually. If timeout is 0, SIGKILL will be used immediately to kill the
295
284
// container.
296
285
func (c * Container ) StopWithTimeout (timeout uint ) (finalErr error ) {
286
+ // Have to lock the pod the container is a part of.
287
+ // This prevents running `podman stop` at the same time a
288
+ // `podman pod start` is running, which could lead to weird races.
289
+ // Pod locks come before container locks, so do this first.
290
+ if c .config .Pod != "" {
291
+ // If we get an error, the pod was probably removed.
292
+ // So we get an expected ErrCtrRemoved instead of ErrPodRemoved,
293
+ // just ignore this and move on to syncing the container.
294
+ pod , _ := c .runtime .state .Pod (c .config .Pod )
295
+ if pod != nil {
296
+ pod .lock .Lock ()
297
+ defer pod .lock .Unlock ()
298
+ }
299
+ }
300
+
297
301
if ! c .batched {
298
302
c .lock .Lock ()
299
303
defer c .lock .Unlock ()
@@ -852,58 +856,7 @@ func (c *Container) Cleanup(ctx context.Context, onlyStopped bool) error {
852
856
}
853
857
}
854
858
855
- // Check if state is good
856
- if ! c .ensureState (define .ContainerStateConfigured , define .ContainerStateCreated , define .ContainerStateStopped , define .ContainerStateStopping , define .ContainerStateExited ) {
857
- return fmt .Errorf ("container %s is running or paused, refusing to clean up: %w" , c .ID (), define .ErrCtrStateInvalid )
858
- }
859
- if onlyStopped && ! c .ensureState (define .ContainerStateStopped ) {
860
- return fmt .Errorf ("container %s is not stopped and only cleanup for a stopped container was requested: %w" , c .ID (), define .ErrCtrStateInvalid )
861
- }
862
-
863
- // if the container was not created in the oci runtime or was already cleaned up, then do nothing
864
- if c .ensureState (define .ContainerStateConfigured , define .ContainerStateExited ) {
865
- return nil
866
- }
867
-
868
- // Handle restart policy.
869
- // Returns a bool indicating whether we actually restarted.
870
- // If we did, don't proceed to cleanup - just exit.
871
- didRestart , err := c .handleRestartPolicy (ctx )
872
- if err != nil {
873
- return err
874
- }
875
- if didRestart {
876
- return nil
877
- }
878
-
879
- // If we didn't restart, we perform a normal cleanup
880
-
881
- // make sure all the container processes are terminated if we are running without a pid namespace.
882
- hasPidNs := false
883
- if c .config .Spec .Linux != nil {
884
- for _ , i := range c .config .Spec .Linux .Namespaces {
885
- if i .Type == spec .PIDNamespace {
886
- hasPidNs = true
887
- break
888
- }
889
- }
890
- }
891
- if ! hasPidNs {
892
- // do not fail on errors
893
- _ = c .ociRuntime .KillContainer (c , uint (unix .SIGKILL ), true )
894
- }
895
-
896
- // Check for running exec sessions
897
- sessions , err := c .getActiveExecSessions ()
898
- if err != nil {
899
- return err
900
- }
901
- if len (sessions ) > 0 {
902
- return fmt .Errorf ("container %s has active exec sessions, refusing to clean up: %w" , c .ID (), define .ErrCtrStateInvalid )
903
- }
904
-
905
- defer c .newContainerEvent (events .Cleanup )
906
- return c .cleanup (ctx )
859
+ return c .fullCleanup (ctx , onlyStopped )
907
860
}
908
861
909
862
// Batch starts a batch operation on the given container
0 commit comments