@@ -115,7 +115,7 @@ func (c *Container) ignoreCgroupError(err error) error {
115115 if err == nil {
116116 return nil
117117 }
118- if errors .Is (err , os .ErrNotExist ) && c . runType () == Stopped && ! c .cgroupManager .Exists () {
118+ if errors .Is (err , os .ErrNotExist ) && ! c . hasInit () && ! c .cgroupManager .Exists () {
119119 return nil
120120 }
121121 return err
@@ -364,37 +364,35 @@ func (c *Container) start(process *Process) (retErr error) {
364364func (c * Container ) Signal (s os.Signal ) error {
365365 c .m .Lock ()
366366 defer c .m .Unlock ()
367- status , err := c .currentStatus ()
368- if err != nil {
369- return err
370- }
371- // To avoid a PID reuse attack, don't kill non-running container.
372- switch status {
373- case Running , Created , Paused :
374- default :
375- return ErrNotRunning
376- }
377367
378368 // When a container has its own PID namespace, inside it the init PID
379369 // is 1, and thus it is handled specially by the kernel. In particular,
380370 // killing init with SIGKILL from an ancestor namespace will also kill
381371 // all other processes in that PID namespace (see pid_namespaces(7)).
382372 //
383373 // OTOH, if PID namespace is shared, we should kill all pids to avoid
384- // leftover processes.
374+ // leftover processes. Handle this special case here.
385375 if s == unix .SIGKILL && ! c .config .Namespaces .IsPrivate (configs .NEWPID ) {
386- err = signalAllProcesses (c .cgroupManager , unix .SIGKILL )
387- } else {
388- err = c .initProcess .signal (s )
376+ if err := signalAllProcesses (c .cgroupManager , unix .SIGKILL ); err != nil {
377+ return fmt .Errorf ("unable to kill all processes: %w" , err )
378+ }
379+ return nil
389380 }
390- if err != nil {
381+
382+ // To avoid a PID reuse attack, don't kill non-running container.
383+ if ! c .hasInit () {
384+ return ErrNotRunning
385+ }
386+ if err := c .initProcess .signal (s ); err != nil {
391387 return fmt .Errorf ("unable to signal init: %w" , err )
392388 }
393- if status == Paused && s == unix .SIGKILL {
389+ if s == unix .SIGKILL {
394390 // For cgroup v1, killing a process in a frozen cgroup
395391 // does nothing until it's thawed. Only thaw the cgroup
396392 // for SIGKILL.
397- _ = c .cgroupManager .Freeze (configs .Thawed )
393+ if paused , _ := c .isPaused (); paused {
394+ _ = c .cgroupManager .Freeze (configs .Thawed )
395+ }
398396 }
399397 return nil
400398}
@@ -876,7 +874,10 @@ func (c *Container) newInitConfig(process *Process) *initConfig {
876874func (c * Container ) Destroy () error {
877875 c .m .Lock ()
878876 defer c .m .Unlock ()
879- return c .state .destroy ()
877+ if err := c .state .destroy (); err != nil {
878+ return fmt .Errorf ("unable to destroy container: %w" , err )
879+ }
880+ return nil
880881}
881882
882883// Pause pauses the container, if its state is RUNNING or CREATED, changing
@@ -1006,34 +1007,31 @@ func (c *Container) refreshState() error {
10061007 if paused {
10071008 return c .state .transition (& pausedState {c : c })
10081009 }
1009- t := c .runType ()
1010- switch t {
1011- case Created :
1010+ if ! c .hasInit () {
1011+ return c .state .transition (& stoppedState {c : c })
1012+ }
1013+ // The presence of exec fifo helps to distinguish between
1014+ // the created and the running states.
1015+ if _ , err := os .Stat (filepath .Join (c .stateDir , execFifoFilename )); err == nil {
10121016 return c .state .transition (& createdState {c : c })
1013- case Running :
1014- return c .state .transition (& runningState {c : c })
10151017 }
1016- return c .state .transition (& stoppedState {c : c })
1018+ return c .state .transition (& runningState {c : c })
10171019}
10181020
1019- func (c * Container ) runType () Status {
1021+ // hasInit tells whether the container init process exists.
1022+ func (c * Container ) hasInit () bool {
10201023 if c .initProcess == nil {
1021- return Stopped
1024+ return false
10221025 }
10231026 pid := c .initProcess .pid ()
10241027 stat , err := system .Stat (pid )
10251028 if err != nil {
1026- return Stopped
1029+ return false
10271030 }
10281031 if stat .StartTime != c .initProcessStartTime || stat .State == system .Zombie || stat .State == system .Dead {
1029- return Stopped
1030- }
1031- // We'll create exec fifo and blocking on it after container is created,
1032- // and delete it after start container.
1033- if _ , err := os .Stat (filepath .Join (c .stateDir , execFifoFilename )); err == nil {
1034- return Created
1032+ return false
10351033 }
1036- return Running
1034+ return true
10371035}
10381036
10391037func (c * Container ) isPaused () (bool , error ) {
0 commit comments