...

Source file src/github.com/Microsoft/hcsshim/internal/signals/signal.go

Documentation: github.com/Microsoft/hcsshim/internal/signals

     1  package signals
     2  
     3  import (
     4  	"errors"
     5  	"strconv"
     6  	"strings"
     7  
     8  	"github.com/Microsoft/hcsshim/internal/protocol/guestrequest"
     9  	"github.com/Microsoft/hcsshim/internal/protocol/guestresource"
    10  )
    11  
    12  var (
    13  	// ErrInvalidSignal is the standard error for an invalid signal for a given
    14  	// flavor of container WCOW/LCOW.
    15  	ErrInvalidSignal = errors.New("invalid signal value")
    16  )
    17  
    18  // ValidateSigstrLCOW validates that `sigstr` is an acceptable signal for LCOW
    19  // based on `signalsSupported`.
    20  //
    21  // `sigstr` may either be the text name or integer value of the signal.
    22  //
    23  // If `signalsSupported==false` we verify that only SIGTERM/SIGKILL are sent.
    24  // All other signals are not supported on downlevel platforms.
    25  func ValidateSigstrLCOW(sigstr string, signalsSupported bool) (*guestresource.SignalProcessOptionsLCOW, error) {
    26  	// All flavors including legacy default to SIGTERM on LCOW CtrlC on Windows
    27  	if sigstr == "" {
    28  		if signalsSupported {
    29  			return &guestresource.SignalProcessOptionsLCOW{Signal: sigTerm}, nil
    30  		}
    31  		return nil, nil
    32  	}
    33  
    34  	signal, err := strconv.Atoi(sigstr)
    35  	if err == nil {
    36  		return ValidateLCOW(signal, signalsSupported)
    37  	}
    38  
    39  	sigstr = strings.ToUpper(sigstr)
    40  	if !signalsSupported {
    41  		// If signals arent supported we just validate that its a known signal.
    42  		// We already return 0 since we only supported a platform Kill() at that
    43  		// time.
    44  		switch sigstr {
    45  		case "TERM", "KILL":
    46  			return nil, nil
    47  		default:
    48  			return nil, ErrInvalidSignal
    49  		}
    50  	}
    51  
    52  	// Match signal string name
    53  	for k, v := range signalMapLcow {
    54  		if sigstr == k {
    55  			return &guestresource.SignalProcessOptionsLCOW{Signal: v}, nil
    56  		}
    57  	}
    58  	return nil, ErrInvalidSignal
    59  }
    60  
    61  // ValidateSigstrWCOW validates that `sigstr` is an acceptable signal for WCOW
    62  // based on `signalsSupported`.
    63  //
    64  // `sigstr` may either be the text name or integer value of the signal.
    65  //
    66  // If `signalsSupported==false` we verify that only SIGTERM/SIGKILL and
    67  // CTRLSHUTDOWN are sent. All other signals are not supported on downlevel
    68  // platforms.
    69  //
    70  // By default WCOW orchestrators may still use Linux SIGTERM and SIGKILL
    71  // semantics which will be properly translated to CTRLSHUTDOWN and `Terminate`.
    72  // To detect when WCOW needs to `Terminate` the return signal will be `nil` and
    73  // the return error will be `nil`.
    74  func ValidateSigstrWCOW(sigstr string, signalsSupported bool) (*guestresource.SignalProcessOptionsWCOW, error) {
    75  	// All flavors including legacy default to SIGTERM on LCOW CtrlC on Windows
    76  	if sigstr == "" {
    77  		if signalsSupported {
    78  			return &guestresource.SignalProcessOptionsWCOW{Signal: guestrequest.SignalValueWCOWCtrlShutdown}, nil
    79  		}
    80  		return nil, nil
    81  	}
    82  
    83  	signal, err := strconv.Atoi(sigstr)
    84  	if err == nil {
    85  		return ValidateWCOW(signal, signalsSupported)
    86  	}
    87  
    88  	sigstr = strings.ToUpper(sigstr)
    89  	if !signalsSupported {
    90  		// If signals arent supported we just validate that its a known signal.
    91  		// We already return 0 since we only supported a platform Kill() at that
    92  		// time.
    93  		switch sigstr {
    94  		// Docker sends a UNIX term in the supported Windows Signal map.
    95  		case "CTRLSHUTDOWN", "TERM", "KILL":
    96  			return nil, nil
    97  		default:
    98  			return nil, ErrInvalidSignal
    99  		}
   100  	} else {
   101  		// Docker sends the UNIX signal name or value. Convert them to the
   102  		// correct Windows signals.
   103  
   104  		var signalString guestrequest.SignalValueWCOW
   105  		switch sigstr {
   106  		case "CTRLC":
   107  			signalString = guestrequest.SignalValueWCOWCtrlC
   108  		case "CTRLBREAK":
   109  			signalString = guestrequest.SignalValueWCOWCtrlBreak
   110  		case "CTRLCLOSE":
   111  			signalString = guestrequest.SignalValueWCOWCtrlClose
   112  		case "CTRLLOGOFF":
   113  			signalString = guestrequest.SignalValueWCOWCtrlLogOff
   114  		case "CTRLSHUTDOWN", "TERM":
   115  			// SIGTERM is most like CtrlShutdown on Windows convert it here.
   116  			signalString = guestrequest.SignalValueWCOWCtrlShutdown
   117  		case "KILL":
   118  			return nil, nil
   119  		default:
   120  			return nil, ErrInvalidSignal
   121  		}
   122  
   123  		return &guestresource.SignalProcessOptionsWCOW{Signal: signalString}, nil
   124  	}
   125  }
   126  
   127  // ValidateLCOW validates that `signal` is an acceptable signal for LCOW based
   128  // on `signalsSupported`.
   129  //
   130  // If `signalsSupported==false` we verify that only SIGTERM/SIGKILL are sent.
   131  // All other signals are not supported on downlevel platforms.
   132  func ValidateLCOW(signal int, signalsSupported bool) (*guestresource.SignalProcessOptionsLCOW, error) {
   133  	if !signalsSupported {
   134  		// If signals arent supported we just validate that its a known signal.
   135  		// We already return 0 since we only supported a platform Kill() at that
   136  		// time.
   137  		switch signal {
   138  		case ctrlShutdown, sigTerm, sigKill:
   139  			return nil, nil
   140  		default:
   141  			return nil, ErrInvalidSignal
   142  		}
   143  	}
   144  
   145  	// Match signal by value
   146  	for _, v := range signalMapLcow {
   147  		if signal == v {
   148  			return &guestresource.SignalProcessOptionsLCOW{Signal: signal}, nil
   149  		}
   150  	}
   151  	return nil, ErrInvalidSignal
   152  }
   153  
   154  // ValidateWCOW validates that `signal` is an acceptable signal for WCOW based
   155  // on `signalsSupported`.
   156  //
   157  // If `signalsSupported==false` we verify that only SIGTERM/SIGKILL and
   158  // CTRLSHUTDOWN are sent. All other signals are not supported on downlevel
   159  // platforms.
   160  //
   161  // By default WCOW orchestrators may still use Linux SIGTERM and SIGKILL
   162  // semantics which will be properly translated to CTRLSHUTDOWN and `Terminate`.
   163  // To detect when WCOW needs to `Terminate` the return signal will be `nil` and
   164  // the return error will be `nil`.
   165  func ValidateWCOW(signal int, signalsSupported bool) (*guestresource.SignalProcessOptionsWCOW, error) {
   166  	if !signalsSupported {
   167  		// If signals arent supported we just validate that its a known signal.
   168  		// We already return 0 since we only supported a platform Kill() at that
   169  		// time.
   170  		switch signal {
   171  		// Docker sends a UNIX term in the supported Windows Signal map.
   172  		case ctrlShutdown, sigTerm, sigKill:
   173  			return nil, nil
   174  		default:
   175  			return nil, ErrInvalidSignal
   176  		}
   177  	} else {
   178  		// Docker sends the UNIX signal name or value. Convert them to the
   179  		// correct Windows signals.
   180  
   181  		var signalString guestrequest.SignalValueWCOW
   182  		switch signal {
   183  		case ctrlC:
   184  			signalString = guestrequest.SignalValueWCOWCtrlC
   185  		case ctrlBreak:
   186  			signalString = guestrequest.SignalValueWCOWCtrlBreak
   187  		case ctrlClose:
   188  			signalString = guestrequest.SignalValueWCOWCtrlClose
   189  		case ctrlLogOff:
   190  			signalString = guestrequest.SignalValueWCOWCtrlLogOff
   191  		case ctrlShutdown, sigTerm:
   192  			// sigTerm is most like CtrlShutdown on Windows convert it here.
   193  			signalString = guestrequest.SignalValueWCOWCtrlShutdown
   194  		case sigKill:
   195  			return nil, nil
   196  		default:
   197  			return nil, ErrInvalidSignal
   198  		}
   199  
   200  		return &guestresource.SignalProcessOptionsWCOW{Signal: signalString}, nil
   201  	}
   202  }
   203  

View as plain text