Nathan Gieseker 9a429d8d25 Windows: Updates Windows Vendoring
Updates windows dependent libraries for vendoing.
2019-01-23 18:43:18 -08:00

179 lines
4.0 KiB
Go

package main
import (
"strconv"
"strings"
"github.com/Microsoft/hcsshim/internal/appargs"
"github.com/Microsoft/hcsshim/internal/guestrequest"
"github.com/Microsoft/hcsshim/internal/hcs"
"github.com/Microsoft/hcsshim/internal/schema1"
"github.com/Microsoft/hcsshim/osversion"
"github.com/pkg/errors"
"github.com/urfave/cli"
)
var killCommand = cli.Command{
Name: "kill",
Usage: "kill sends the specified signal (default: SIGTERM) to the container's init process",
ArgsUsage: `<container-id> [signal]
Where "<container-id>" is the name for the instance of the container and
"[signal]" is the signal to be sent to the init process.
EXAMPLE:
For example, if the container id is "ubuntu01" the following will send a "KILL"
signal to the init process of the "ubuntu01" container:
# runhcs kill ubuntu01 KILL`,
Flags: []cli.Flag{},
Before: appargs.Validate(argID, appargs.Optional(appargs.String)),
Action: func(context *cli.Context) error {
id := context.Args().First()
c, err := getContainer(id, true)
if err != nil {
return err
}
defer c.Close()
status, err := c.Status()
if err != nil {
return err
}
if status != containerRunning {
return errContainerStopped
}
signalsSupported := false
// The Signal feature was added in RS5
if osversion.Get().Build >= osversion.RS5 {
if c.IsHost || c.HostID != "" {
var hostID string
if c.IsHost {
// This is the LCOW, Pod Sandbox, or Windows Xenon V2 for RS5+
hostID = vmID(c.ID)
} else {
// This is the Nth container in a Pod
hostID = c.HostID
}
uvm, err := hcs.OpenComputeSystem(hostID)
if err != nil {
return err
}
defer uvm.Close()
if props, err := uvm.Properties(schema1.PropertyTypeGuestConnection); err == nil &&
props.GuestConnectionInfo.GuestDefinedCapabilities.SignalProcessSupported {
signalsSupported = true
}
} else if c.Spec.Linux == nil && c.Spec.Windows.HyperV == nil {
// RS5+ Windows Argon
signalsSupported = true
}
}
signal := 0
if signalsSupported {
signal, err = validateSigstr(context.Args().Get(1), signalsSupported, c.Spec.Linux != nil)
if err != nil {
return err
}
}
var pid int
if err := stateKey.Get(id, keyInitPid, &pid); err != nil {
return err
}
p, err := c.hc.OpenProcess(pid)
if err != nil {
return err
}
defer p.Close()
if signalsSupported && (c.Spec.Linux != nil || !c.Spec.Process.Terminal) {
opts := guestrequest.SignalProcessOptions{
Signal: signal,
}
return p.Signal(opts)
}
// Legacy signal issue a kill
return p.Kill()
},
}
func validateSigstr(sigstr string, signalsSupported bool, isLcow bool) (int, error) {
errInvalidSignal := errors.Errorf("invalid signal '%s'", sigstr)
// All flavors including legacy default to SIGTERM on LCOW CtrlC on Windows
if sigstr == "" {
if isLcow {
return 0xf, nil
}
return 0, nil
}
sigstr = strings.ToUpper(sigstr)
if !signalsSupported {
// If signals arent supported we just validate that its a known signal.
// We already return 0 since we only supported a platform Kill() at that
// time.
if isLcow {
switch sigstr {
case "15":
fallthrough
case "TERM":
fallthrough
case "SIGTERM":
return 0, nil
default:
return 0, errInvalidSignal
}
}
switch sigstr {
// Docker sends a UNIX term in the supported Windows Signal map.
case "15":
fallthrough
case "TERM":
fallthrough
case "0":
fallthrough
case "CTRLC":
return 0, nil
case "9":
fallthrough
case "KILL":
return 0, nil
default:
return 0, errInvalidSignal
}
}
var sigmap map[string]int
if isLcow {
sigmap = signalMapLcow
} else {
sigmap = signalMapWindows
}
signal, err := strconv.Atoi(sigstr)
if err != nil {
// Signal might still match the string value
for k, v := range sigmap {
if k == sigstr {
return v, nil
}
}
return 0, errInvalidSignal
}
// Match signal by value
for _, v := range sigmap {
if signal == v {
return signal, nil
}
}
return 0, errInvalidSignal
}