github.com/metacubex/gvisor@v0.0.0-20240320004321-933faba989ec/pkg/shim/proc/exec_state.go (about)

     1  // Copyright 2018 The containerd Authors.
     2  // Copyright 2018 The gVisor Authors.
     3  //
     4  // Licensed under the Apache License, Version 2.0 (the "License");
     5  // you may not use this file except in compliance with the License.
     6  // You may obtain a copy of the License at
     7  //
     8  //     https://www.apache.org/licenses/LICENSE-2.0
     9  //
    10  // Unless required by applicable law or agreed to in writing, software
    11  // distributed under the License is distributed on an "AS IS" BASIS,
    12  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  // See the License for the specific language governing permissions and
    14  // limitations under the License.
    15  
    16  package proc
    17  
    18  import (
    19  	"context"
    20  	"fmt"
    21  
    22  	"github.com/containerd/console"
    23  )
    24  
    25  type execState interface {
    26  	Resize(console.WinSize) error
    27  	Start(context.Context) error
    28  	Delete(context.Context) error
    29  	Kill(context.Context, uint32, bool) error
    30  	SetExited(int)
    31  }
    32  
    33  type execCreatedState struct {
    34  	p *execProcess
    35  }
    36  
    37  func (s *execCreatedState) name() string {
    38  	return "created"
    39  }
    40  
    41  func (s *execCreatedState) transition(transition stateTransition) {
    42  	switch transition {
    43  	case running:
    44  		s.p.execState = &execRunningState{p: s.p}
    45  	case stopped:
    46  		s.p.execState = &execStoppedState{p: s.p}
    47  	case deleted:
    48  		s.p.execState = &deletedState{}
    49  	default:
    50  		panic(fmt.Sprintf("invalid state transition %q to %q", s.name(), transition))
    51  	}
    52  }
    53  
    54  func (s *execCreatedState) Resize(ws console.WinSize) error {
    55  	return s.p.resize(ws)
    56  }
    57  
    58  func (s *execCreatedState) Start(ctx context.Context) error {
    59  	if err := s.p.start(ctx); err != nil {
    60  		return err
    61  	}
    62  	s.transition(running)
    63  	return nil
    64  }
    65  
    66  func (s *execCreatedState) Delete(context.Context) error {
    67  	s.p.delete()
    68  	s.transition(deleted)
    69  	return nil
    70  }
    71  
    72  func (s *execCreatedState) Kill(ctx context.Context, sig uint32, all bool) error {
    73  	return s.p.kill(ctx, sig, all)
    74  }
    75  
    76  func (s *execCreatedState) SetExited(status int) {
    77  	s.p.setExited(status)
    78  	s.transition(stopped)
    79  }
    80  
    81  type execRunningState struct {
    82  	p *execProcess
    83  }
    84  
    85  func (s *execRunningState) name() string {
    86  	return "running"
    87  }
    88  
    89  func (s *execRunningState) transition(transition stateTransition) {
    90  	switch transition {
    91  	case stopped:
    92  		s.p.execState = &execStoppedState{p: s.p}
    93  	default:
    94  		panic(fmt.Sprintf("invalid state transition %q to %q", s.name(), transition))
    95  	}
    96  }
    97  
    98  func (s *execRunningState) Resize(ws console.WinSize) error {
    99  	return s.p.resize(ws)
   100  }
   101  
   102  func (s *execRunningState) Start(context.Context) error {
   103  	return fmt.Errorf("cannot start a running process")
   104  }
   105  
   106  func (s *execRunningState) Delete(context.Context) error {
   107  	return fmt.Errorf("cannot delete a running process")
   108  }
   109  
   110  func (s *execRunningState) Kill(ctx context.Context, sig uint32, all bool) error {
   111  	return s.p.kill(ctx, sig, all)
   112  }
   113  
   114  func (s *execRunningState) SetExited(status int) {
   115  	s.p.setExited(status)
   116  	s.transition(stopped)
   117  }
   118  
   119  type execStoppedState struct {
   120  	p *execProcess
   121  }
   122  
   123  func (s *execStoppedState) name() string {
   124  	return "stopped"
   125  }
   126  
   127  func (s *execStoppedState) transition(transition stateTransition) {
   128  	switch transition {
   129  	case deleted:
   130  		s.p.execState = &deletedState{}
   131  	default:
   132  		panic(fmt.Sprintf("invalid state transition %q to %q", s.name(), transition))
   133  	}
   134  }
   135  
   136  func (s *execStoppedState) Resize(console.WinSize) error {
   137  	return fmt.Errorf("cannot resize a stopped container")
   138  }
   139  
   140  func (s *execStoppedState) Start(context.Context) error {
   141  	return fmt.Errorf("cannot start a stopped process")
   142  }
   143  
   144  func (s *execStoppedState) Delete(context.Context) error {
   145  	s.p.delete()
   146  	s.transition(deleted)
   147  	return nil
   148  }
   149  
   150  func (s *execStoppedState) Kill(_ context.Context, sig uint32, _ bool) error {
   151  	return handleStoppedKill(sig)
   152  }
   153  
   154  func (s *execStoppedState) SetExited(int) {
   155  	// no op
   156  }