зеркало из https://github.com/microsoft/docker.git
Merge pull request #16997 from Microsoft/10662-kill-parttwo
Windows: [TP4] docker kill handling part two
This commit is contained in:
Коммит
e1804098b9
|
@ -18,6 +18,7 @@ func (d *Driver) Exec(c *execdriver.Command, processConfig *execdriver.ProcessCo
|
||||||
term execdriver.Terminal
|
term execdriver.Terminal
|
||||||
err error
|
err error
|
||||||
exitCode int32
|
exitCode int32
|
||||||
|
errno uint32
|
||||||
)
|
)
|
||||||
|
|
||||||
active := d.activeContainers[c.ID]
|
active := d.activeContainers[c.ID]
|
||||||
|
@ -77,12 +78,15 @@ func (d *Driver) Exec(c *execdriver.Command, processConfig *execdriver.ProcessCo
|
||||||
hooks.Start(&c.ProcessConfig, int(pid), chOOM)
|
hooks.Start(&c.ProcessConfig, int(pid), chOOM)
|
||||||
}
|
}
|
||||||
|
|
||||||
if exitCode, err = hcsshim.WaitForProcessInComputeSystem(c.ID, pid); err != nil {
|
if exitCode, errno, err = hcsshim.WaitForProcessInComputeSystem(c.ID, pid, hcsshim.TimeoutInfinite); err != nil {
|
||||||
logrus.Errorf("Failed to WaitForProcessInComputeSystem %s", err)
|
if errno == hcsshim.Win32PipeHasBeenEnded {
|
||||||
|
logrus.Debugf("Exiting Run() after WaitForProcessInComputeSystem failed with recognised error 0x%X", errno)
|
||||||
|
return hcsshim.WaitErrExecFailed, nil
|
||||||
|
}
|
||||||
|
logrus.Warnf("WaitForProcessInComputeSystem failed (container may have been killed): 0x%X %s", errno, err)
|
||||||
return -1, err
|
return -1, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Windows - Do something with this exit code
|
logrus.Debugln("Exiting Run()", c.ID)
|
||||||
logrus.Debugln("Exiting Run() with ExitCode 0", c.ID)
|
|
||||||
return int(exitCode), nil
|
return int(exitCode), nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -220,22 +220,19 @@ func (d *Driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, hooks execd
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
// Stop the container
|
// Stop the container
|
||||||
|
if forceKill {
|
||||||
if terminateMode {
|
logrus.Debugf("Forcibly terminating container %s", c.ID)
|
||||||
logrus.Debugf("Terminating container %s", c.ID)
|
if errno, err := hcsshim.TerminateComputeSystem(c.ID, hcsshim.TimeoutInfinite, "exec-run-defer"); err != nil {
|
||||||
if err := hcsshim.TerminateComputeSystem(c.ID); err != nil {
|
logrus.Warnf("Ignoring error from TerminateComputeSystem 0x%X %s", errno, err)
|
||||||
// IMPORTANT: Don't fail if fails to change state. It could already
|
|
||||||
// have been stopped through kill().
|
|
||||||
// Otherwise, the docker daemon will hang in job wait()
|
|
||||||
logrus.Warnf("Ignoring error from TerminateComputeSystem %s", err)
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logrus.Debugf("Shutting down container %s", c.ID)
|
logrus.Debugf("Shutting down container %s", c.ID)
|
||||||
if err := hcsshim.ShutdownComputeSystem(c.ID); err != nil {
|
if errno, err := hcsshim.ShutdownComputeSystem(c.ID, hcsshim.TimeoutInfinite, "exec-run-defer"); err != nil {
|
||||||
// IMPORTANT: Don't fail if fails to change state. It could already
|
if errno != hcsshim.Win32SystemShutdownIsInProgress &&
|
||||||
// have been stopped through kill().
|
errno != hcsshim.Win32SpecifiedPathInvalid &&
|
||||||
// Otherwise, the docker daemon will hang in job wait()
|
errno != hcsshim.Win32SystemCannotFindThePathSpecified {
|
||||||
logrus.Warnf("Ignoring error from ShutdownComputeSystem %s", err)
|
logrus.Warnf("Ignoring error from ShutdownComputeSystem 0x%X %s", errno, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
@ -303,11 +300,20 @@ func (d *Driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, hooks execd
|
||||||
hooks.Start(&c.ProcessConfig, int(pid), chOOM)
|
hooks.Start(&c.ProcessConfig, int(pid), chOOM)
|
||||||
}
|
}
|
||||||
|
|
||||||
var exitCode int32
|
var (
|
||||||
exitCode, err = hcsshim.WaitForProcessInComputeSystem(c.ID, pid)
|
exitCode int32
|
||||||
|
errno uint32
|
||||||
|
)
|
||||||
|
exitCode, errno, err = hcsshim.WaitForProcessInComputeSystem(c.ID, pid, hcsshim.TimeoutInfinite)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Errorf("Failed to WaitForProcessInComputeSystem %s", err)
|
if errno != hcsshim.Win32PipeHasBeenEnded {
|
||||||
return execdriver.ExitStatus{ExitCode: -1}, err
|
logrus.Warnf("WaitForProcessInComputeSystem failed (container may have been killed): %s", err)
|
||||||
|
}
|
||||||
|
// Do NOT return err here as the container would have
|
||||||
|
// started, otherwise docker will deadlock. It's perfectly legitimate
|
||||||
|
// for WaitForProcessInComputeSystem to fail in situations such
|
||||||
|
// as the container being killed on another thread.
|
||||||
|
return execdriver.ExitStatus{ExitCode: hcsshim.WaitErrExecFailed}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
logrus.Debugf("Exiting Run() exitCode %d id=%s", exitCode, c.ID)
|
logrus.Debugf("Exiting Run() exitCode %d id=%s", exitCode, c.ID)
|
||||||
|
|
|
@ -3,6 +3,9 @@
|
||||||
package windows
|
package windows
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
"github.com/Sirupsen/logrus"
|
"github.com/Sirupsen/logrus"
|
||||||
"github.com/docker/docker/daemon/execdriver"
|
"github.com/docker/docker/daemon/execdriver"
|
||||||
"github.com/microsoft/hcsshim"
|
"github.com/microsoft/hcsshim"
|
||||||
|
@ -10,37 +13,36 @@ import (
|
||||||
|
|
||||||
// Terminate implements the exec driver Driver interface.
|
// Terminate implements the exec driver Driver interface.
|
||||||
func (d *Driver) Terminate(p *execdriver.Command) error {
|
func (d *Driver) Terminate(p *execdriver.Command) error {
|
||||||
logrus.Debugf("WindowsExec: Terminate() id=%s", p.ID)
|
return kill(p.ID, p.ContainerPid, syscall.SIGTERM)
|
||||||
return kill(p.ID, p.ContainerPid)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Kill implements the exec driver Driver interface.
|
// Kill implements the exec driver Driver interface.
|
||||||
func (d *Driver) Kill(p *execdriver.Command, sig int) error {
|
func (d *Driver) Kill(p *execdriver.Command, sig int) error {
|
||||||
logrus.Debugf("WindowsExec: Kill() id=%s sig=%d", p.ID, sig)
|
return kill(p.ID, p.ContainerPid, syscall.Signal(sig))
|
||||||
return kill(p.ID, p.ContainerPid)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func kill(id string, pid int) error {
|
func kill(id string, pid int, sig syscall.Signal) error {
|
||||||
logrus.Debugln("kill() ", id, pid)
|
logrus.Debugf("WindowsExec: kill() id=%s pid=%d sig=%d", id, pid, sig)
|
||||||
var err error
|
var err error
|
||||||
|
context := fmt.Sprintf("kill: sig=%d pid=%d", sig, pid)
|
||||||
|
|
||||||
// Terminate Process
|
if sig == syscall.SIGKILL || forceKill {
|
||||||
if err = hcsshim.TerminateProcessInComputeSystem(id, uint32(pid)); err != nil {
|
|
||||||
logrus.Warnf("Failed to terminate pid %d in %s: %q", pid, id, err)
|
|
||||||
// Ignore errors
|
|
||||||
err = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if terminateMode {
|
|
||||||
// Terminate the compute system
|
// Terminate the compute system
|
||||||
if err = hcsshim.TerminateComputeSystem(id); err != nil {
|
if errno, err := hcsshim.TerminateComputeSystem(id, hcsshim.TimeoutInfinite, context); err != nil {
|
||||||
logrus.Errorf("Failed to terminate %s - %q", id, err)
|
logrus.Errorf("Failed to terminate %s - 0x%X %q", id, errno, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
// Terminate Process
|
||||||
|
if err = hcsshim.TerminateProcessInComputeSystem(id, uint32(pid)); err != nil {
|
||||||
|
logrus.Warnf("Failed to terminate pid %d in %s: %q", pid, id, err)
|
||||||
|
// Ignore errors
|
||||||
|
err = nil
|
||||||
|
}
|
||||||
|
|
||||||
// Shutdown the compute system
|
// Shutdown the compute system
|
||||||
if err = hcsshim.ShutdownComputeSystem(id); err != nil {
|
if errno, err := hcsshim.ShutdownComputeSystem(id, hcsshim.TimeoutInfinite, context); err != nil {
|
||||||
logrus.Errorf("Failed to shutdown %s - %q", id, err)
|
logrus.Errorf("Failed to shutdown %s - 0x%X %q", id, errno, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -18,7 +18,8 @@ import (
|
||||||
var dummyMode bool
|
var dummyMode bool
|
||||||
|
|
||||||
// This allows the daemon to terminate containers rather than shutdown
|
// This allows the daemon to terminate containers rather than shutdown
|
||||||
var terminateMode bool
|
// This allows the daemon to force kill (HCS terminate) rather than shutdown
|
||||||
|
var forceKill bool
|
||||||
|
|
||||||
// Define name and version for windows
|
// Define name and version for windows
|
||||||
var (
|
var (
|
||||||
|
@ -62,11 +63,11 @@ func NewDriver(root, initPath string, options []string) (*Driver, error) {
|
||||||
logrus.Warn("Using dummy mode in Windows exec driver. This is for development use only!")
|
logrus.Warn("Using dummy mode in Windows exec driver. This is for development use only!")
|
||||||
}
|
}
|
||||||
|
|
||||||
case "terminate":
|
case "forcekill":
|
||||||
switch val {
|
switch val {
|
||||||
case "1":
|
case "1":
|
||||||
terminateMode = true
|
forceKill = true
|
||||||
logrus.Warn("Using terminate mode in Windows exec driver. This is for testing purposes only.")
|
logrus.Warn("Using force kill mode in Windows exec driver. This is for testing purposes only.")
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
package daemon
|
package daemon
|
||||||
|
|
||||||
import "syscall"
|
import (
|
||||||
|
"fmt"
|
||||||
|
"runtime"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/docker/docker/pkg/signal"
|
||||||
|
)
|
||||||
|
|
||||||
// ContainerKill send signal to the container
|
// ContainerKill send signal to the container
|
||||||
// If no signal is given (sig 0), then Kill with SIGKILL and wait
|
// If no signal is given (sig 0), then Kill with SIGKILL and wait
|
||||||
|
@ -12,6 +18,10 @@ func (daemon *Daemon) ContainerKill(name string, sig uint64) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if sig != 0 && !signal.ValidSignalForPlatform(syscall.Signal(sig)) {
|
||||||
|
return fmt.Errorf("The %s daemon does not support signal %d", runtime.GOOS, sig)
|
||||||
|
}
|
||||||
|
|
||||||
// If no signal is passed, or SIGKILL, perform regular Kill (SIGKILL + wait())
|
// If no signal is passed, or SIGKILL, perform regular Kill (SIGKILL + wait())
|
||||||
if sig == 0 || syscall.Signal(sig) == syscall.SIGKILL {
|
if sig == 0 || syscall.Signal(sig) == syscall.SIGKILL {
|
||||||
if err := container.Kill(); err != nil {
|
if err := container.Kill(); err != nil {
|
||||||
|
|
|
@ -14,7 +14,7 @@ clone git github.com/gorilla/context 14f550f51a
|
||||||
clone git github.com/gorilla/mux e444e69cbd
|
clone git github.com/gorilla/mux e444e69cbd
|
||||||
clone git github.com/kr/pty 5cf931ef8f
|
clone git github.com/kr/pty 5cf931ef8f
|
||||||
clone git github.com/mattn/go-sqlite3 v1.1.0
|
clone git github.com/mattn/go-sqlite3 v1.1.0
|
||||||
clone git github.com/microsoft/hcsshim 7f646aa6b26bcf90caee91e93cde4a80d0d8a83e
|
clone git github.com/microsoft/hcsshim 325e531f8c49dd78580d5fd197ddb972fa4610e7
|
||||||
clone git github.com/mistifyio/go-zfs v2.1.1
|
clone git github.com/mistifyio/go-zfs v2.1.1
|
||||||
clone git github.com/tchap/go-patricia v2.1.0
|
clone git github.com/tchap/go-patricia v2.1.0
|
||||||
clone git golang.org/x/net 3cffabab72adf04f8e3b01c5baf775361837b5fe https://github.com/golang/net.git
|
clone git golang.org/x/net 3cffabab72adf04f8e3b01c5baf775361837b5fe https://github.com/golang/net.git
|
||||||
|
|
|
@ -42,3 +42,13 @@ func ParseSignal(rawSignal string) (syscall.Signal, error) {
|
||||||
}
|
}
|
||||||
return signal, nil
|
return signal, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ValidSignalForPlatform returns true if a signal is valid on the platform
|
||||||
|
func ValidSignalForPlatform(sig syscall.Signal) bool {
|
||||||
|
for _, v := range SignalMap {
|
||||||
|
if v == sig {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ import (
|
||||||
// An activated layer must later be deactivated via DeactivateLayer.
|
// An activated layer must later be deactivated via DeactivateLayer.
|
||||||
func ActivateLayer(info DriverInfo, id string) error {
|
func ActivateLayer(info DriverInfo, id string) error {
|
||||||
title := "hcsshim::ActivateLayer "
|
title := "hcsshim::ActivateLayer "
|
||||||
logrus.Debugf(title+"Flavour %s ID %s", info.Flavour, id)
|
logrus.Debugf(title+"Flavour %d ID %s", info.Flavour, id)
|
||||||
|
|
||||||
// Load the DLL and get a handle to the procedure we need
|
// Load the DLL and get a handle to the procedure we need
|
||||||
dll, proc, err := loadAndFind(procActivateLayer)
|
dll, proc, err := loadAndFind(procActivateLayer)
|
||||||
|
|
|
@ -12,7 +12,7 @@ import (
|
||||||
// the parent layer provided.
|
// the parent layer provided.
|
||||||
func CreateLayer(info DriverInfo, id, parent string) error {
|
func CreateLayer(info DriverInfo, id, parent string) error {
|
||||||
title := "hcsshim::CreateLayer "
|
title := "hcsshim::CreateLayer "
|
||||||
logrus.Debugf(title+"Flavour %s ID %s parent %s", info.Flavour, id, parent)
|
logrus.Debugf(title+"Flavour %d ID %s parent %s", info.Flavour, id, parent)
|
||||||
|
|
||||||
// Load the DLL and get a handle to the procedure we need
|
// Load the DLL and get a handle to the procedure we need
|
||||||
dll, proc, err := loadAndFind(procCreateLayer)
|
dll, proc, err := loadAndFind(procCreateLayer)
|
||||||
|
|
|
@ -70,7 +70,7 @@ func (p *pipe) Write(b []byte) (int, error) {
|
||||||
func CreateProcessInComputeSystem(id string, useStdin bool, useStdout bool, useStderr bool, params CreateProcessParams) (processid uint32, stdin io.WriteCloser, stdout io.ReadCloser, stderr io.ReadCloser, err error) {
|
func CreateProcessInComputeSystem(id string, useStdin bool, useStdout bool, useStderr bool, params CreateProcessParams) (processid uint32, stdin io.WriteCloser, stdout io.ReadCloser, stderr io.ReadCloser, err error) {
|
||||||
|
|
||||||
title := "HCSShim::CreateProcessInComputeSystem"
|
title := "HCSShim::CreateProcessInComputeSystem"
|
||||||
logrus.Debugf(title+"id=%s params=%s", id, params)
|
logrus.Debugf(title+" id=%s", id)
|
||||||
|
|
||||||
// Load the DLL and get a handle to the procedure we need
|
// Load the DLL and get a handle to the procedure we need
|
||||||
dll, proc, err := loadAndFind(procCreateProcessWithStdHandlesInComputeSystem)
|
dll, proc, err := loadAndFind(procCreateProcessWithStdHandlesInComputeSystem)
|
||||||
|
@ -110,7 +110,7 @@ func CreateProcessInComputeSystem(id string, useStdin bool, useStdout bool, useS
|
||||||
// Get a POINTER to variable to take the pid outparm
|
// Get a POINTER to variable to take the pid outparm
|
||||||
pid := new(uint32)
|
pid := new(uint32)
|
||||||
|
|
||||||
logrus.Debugf(title+" - Calling the procedure itself %s %s", id, paramsJson)
|
logrus.Debugf(title+" - Calling Win32 %s %s", id, paramsJson)
|
||||||
|
|
||||||
var stdinHandle, stdoutHandle, stderrHandle syscall.Handle
|
var stdinHandle, stdoutHandle, stderrHandle syscall.Handle
|
||||||
var stdinParam, stdoutParam, stderrParam uintptr
|
var stdinParam, stdoutParam, stderrParam uintptr
|
||||||
|
|
|
@ -11,7 +11,7 @@ import (
|
||||||
// DeactivateLayer will dismount a layer that was mounted via ActivateLayer.
|
// DeactivateLayer will dismount a layer that was mounted via ActivateLayer.
|
||||||
func DeactivateLayer(info DriverInfo, id string) error {
|
func DeactivateLayer(info DriverInfo, id string) error {
|
||||||
title := "hcsshim::DeactivateLayer "
|
title := "hcsshim::DeactivateLayer "
|
||||||
logrus.Debugf(title+"Flavour %s ID %s", info.Flavour, id)
|
logrus.Debugf(title+"Flavour %d ID %s", info.Flavour, id)
|
||||||
|
|
||||||
// Load the DLL and get a handle to the procedure we need
|
// Load the DLL and get a handle to the procedure we need
|
||||||
dll, proc, err := loadAndFind(procDeactivateLayer)
|
dll, proc, err := loadAndFind(procDeactivateLayer)
|
||||||
|
@ -53,6 +53,6 @@ func DeactivateLayer(info DriverInfo, id string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
logrus.Debugf(title+" - succeeded id=%s flavour=%d", id, info.Flavour)
|
logrus.Debugf(title+"succeeded flavour=%d id=%s", info.Flavour, id)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ import (
|
||||||
// id, including that layer's containing folder, if any.
|
// id, including that layer's containing folder, if any.
|
||||||
func DestroyLayer(info DriverInfo, id string) error {
|
func DestroyLayer(info DriverInfo, id string) error {
|
||||||
title := "hcsshim::DestroyLayer "
|
title := "hcsshim::DestroyLayer "
|
||||||
logrus.Debugf(title+"Flavour %s ID %s", info.Flavour, id)
|
logrus.Debugf(title+"Flavour %d ID %s", info.Flavour, id)
|
||||||
|
|
||||||
// Load the DLL and get a handle to the procedure we need
|
// Load the DLL and get a handle to the procedure we need
|
||||||
dll, proc, err := loadAndFind(procDestroyLayer)
|
dll, proc, err := loadAndFind(procDestroyLayer)
|
||||||
|
@ -54,6 +54,6 @@ func DestroyLayer(info DriverInfo, id string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
logrus.Debugf(title+" - succeeded id=%s flavour=%d", id, info.Flavour)
|
logrus.Debugf(title+"succeeded flavour=%d id=%s", info.Flavour, id)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,6 +83,6 @@ func ExportLayer(info DriverInfo, layerId string, exportFolderPath string, paren
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
logrus.Debugf(title+"- succeeded layerId=%s flavour=%d folder=%s", layerId, info.Flavour, exportFolderPath)
|
logrus.Debugf(title+"succeeded flavour=%d layerId=%s folder=%s", info.Flavour, layerId, exportFolderPath)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ import (
|
||||||
// folder path at which the layer is stored.
|
// folder path at which the layer is stored.
|
||||||
func GetLayerMountPath(info DriverInfo, id string) (string, error) {
|
func GetLayerMountPath(info DriverInfo, id string) (string, error) {
|
||||||
title := "hcsshim::GetLayerMountPath "
|
title := "hcsshim::GetLayerMountPath "
|
||||||
logrus.Debugf(title+"Flavour %s ID %s", info.Flavour, id)
|
logrus.Debugf(title+"Flavour %d ID %s", info.Flavour, id)
|
||||||
|
|
||||||
// Load the DLL and get a handle to the procedure we need
|
// Load the DLL and get a handle to the procedure we need
|
||||||
dll, proc, err := loadAndFind(procGetLayerMountPath)
|
dll, proc, err := loadAndFind(procGetLayerMountPath)
|
||||||
|
@ -86,6 +86,6 @@ func GetLayerMountPath(info DriverInfo, id string) (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
path := syscall.UTF16ToString(mountPathp[0:])
|
path := syscall.UTF16ToString(mountPathp[0:])
|
||||||
logrus.Debugf(title+" - succeeded id=%s flavour=%d path=%s", id, info.Flavour, path)
|
logrus.Debugf(title+"succeeded flavour=%d id=%s path=%s", info.Flavour, id, path)
|
||||||
return path, nil
|
return path, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,18 @@ const (
|
||||||
|
|
||||||
// Utility functions
|
// Utility functions
|
||||||
procCoTaskMemFree = "CoTaskMemFree"
|
procCoTaskMemFree = "CoTaskMemFree"
|
||||||
|
|
||||||
|
// Specific user-visible exit codes
|
||||||
|
WaitErrExecFailed = 32767
|
||||||
|
|
||||||
|
// Known Win32 RC values which should be trapped
|
||||||
|
Win32PipeHasBeenEnded = 0x8007006d // WaitForProcessInComputeSystem: The pipe has been ended
|
||||||
|
Win32SystemShutdownIsInProgress = 0x8007045B // ShutdownComputeSystem: A system shutdown is in progress
|
||||||
|
Win32SpecifiedPathInvalid = 0x800700A1 // ShutdownComputeSystem: The specified path is invalid
|
||||||
|
Win32SystemCannotFindThePathSpecified = 0x80070003 // ShutdownComputeSystem: The system cannot find the path specified
|
||||||
|
|
||||||
|
// Timeout on wait calls
|
||||||
|
TimeoutInfinite = 0xFFFFFFFF
|
||||||
)
|
)
|
||||||
|
|
||||||
// loadAndFindFromDll finds a procedure in the given DLL. Note we do NOT do lazy loading as
|
// loadAndFindFromDll finds a procedure in the given DLL. Note we do NOT do lazy loading as
|
||||||
|
@ -53,8 +65,6 @@ const (
|
||||||
// if a function can't be found. By explicitly loading, we can control error
|
// if a function can't be found. By explicitly loading, we can control error
|
||||||
// handling gracefully without the daemon terminating.
|
// handling gracefully without the daemon terminating.
|
||||||
func loadAndFindFromDll(dllName, procedure string) (dll *syscall.DLL, proc *syscall.Proc, err error) {
|
func loadAndFindFromDll(dllName, procedure string) (dll *syscall.DLL, proc *syscall.Proc, err error) {
|
||||||
logrus.Debugf("hcsshim::loadAndFindFromDll %s %s", dllName, procedure)
|
|
||||||
|
|
||||||
dll, err = syscall.LoadDLL(dllName)
|
dll, err = syscall.LoadDLL(dllName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("Failed to load %s - error %s", dllName, err)
|
err = fmt.Errorf("Failed to load %s - error %s", dllName, err)
|
||||||
|
|
|
@ -82,6 +82,6 @@ func ImportLayer(info DriverInfo, layerId string, importFolderPath string, paren
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
logrus.Debugf(title+"- succeeded layerId=%s flavour=%d folder=%s", layerId, info.Flavour, importFolderPath)
|
logrus.Debugf(title+"succeeded flavour=%d layerId=%s folder=%s", info.Flavour, layerId, importFolderPath)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ import (
|
||||||
// to the system.
|
// to the system.
|
||||||
func LayerExists(info DriverInfo, id string) (bool, error) {
|
func LayerExists(info DriverInfo, id string) (bool, error) {
|
||||||
title := "hcsshim::LayerExists "
|
title := "hcsshim::LayerExists "
|
||||||
logrus.Debugf(title+"Flavour %s ID %s", info.Flavour, id)
|
logrus.Debugf(title+"Flavour %d ID %s", info.Flavour, id)
|
||||||
|
|
||||||
// Load the DLL and get a handle to the procedure we need
|
// Load the DLL and get a handle to the procedure we need
|
||||||
dll, proc, err := loadAndFind(procLayerExists)
|
dll, proc, err := loadAndFind(procLayerExists)
|
||||||
|
@ -57,6 +57,6 @@ func LayerExists(info DriverInfo, id string) (bool, error) {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
logrus.Debugf(title+" - succeeded id=%s flavour=%d exists=%d", id, info.Flavour, exists)
|
logrus.Debugf(title+"succeeded flavour=%d id=%s exists=%d", info.Flavour, id, exists)
|
||||||
return exists, nil
|
return exists, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,6 +73,6 @@ func PrepareLayer(info DriverInfo, layerId string, parentLayerPaths []string) er
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
logrus.Debugf(title+"- succeeded layerId=%s flavour=%d", layerId, info.Flavour)
|
logrus.Debugf(title+"succeeded flavour=%d layerId=%s", info.Flavour, layerId)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ func ResizeConsoleInComputeSystem(id string, processid uint32, h, w int) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
logrus.Debugf(title+" - succeeded id=%s processid=%d (%d,%d)", id, processid, h, w)
|
logrus.Debugf(title+" succeeded id=%s processid=%d (%d,%d)", id, processid, h, w)
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,50 +0,0 @@
|
||||||
package hcsshim
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
"github.com/Sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ShutdownComputeSystem shuts down a container by requesting a shutdown within
|
|
||||||
// the container operating system.
|
|
||||||
func ShutdownComputeSystem(id string) error {
|
|
||||||
|
|
||||||
var title = "HCSShim::ShutdownComputeSystem"
|
|
||||||
logrus.Debugf(title+" id=%s", id)
|
|
||||||
|
|
||||||
// Load the DLL and get a handle to the procedure we need
|
|
||||||
dll, proc, err := loadAndFind(procShutdownComputeSystem)
|
|
||||||
if dll != nil {
|
|
||||||
defer dll.Release()
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert id to uint16 pointers for calling the procedure
|
|
||||||
idp, err := syscall.UTF16PtrFromString(id)
|
|
||||||
if err != nil {
|
|
||||||
err = fmt.Errorf(title+" - Failed conversion of id %s to pointer %s", id, err)
|
|
||||||
logrus.Error(err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
timeout := uint32(0xffffffff)
|
|
||||||
|
|
||||||
// Call the procedure itself.
|
|
||||||
r1, _, err := proc.Call(
|
|
||||||
uintptr(unsafe.Pointer(idp)), uintptr(timeout))
|
|
||||||
|
|
||||||
use(unsafe.Pointer(idp))
|
|
||||||
|
|
||||||
if r1 != 0 {
|
|
||||||
err = fmt.Errorf(title+" - Win32 API call returned error r1=%d err=%s id=%s", r1, syscall.Errno(r1), id)
|
|
||||||
return syscall.Errno(r1)
|
|
||||||
}
|
|
||||||
|
|
||||||
logrus.Debugf(title+" - succeeded id=%s", id)
|
|
||||||
return nil
|
|
||||||
}
|
|
69
vendor/src/github.com/microsoft/hcsshim/shutdownterminatecomputesystem.go
поставляемый
Normal file
69
vendor/src/github.com/microsoft/hcsshim/shutdownterminatecomputesystem.go
поставляемый
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
package hcsshim
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/Sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TerminateComputeSystem force terminates a container.
|
||||||
|
func TerminateComputeSystem(id string, timeout uint32, context string) (uint32, error) {
|
||||||
|
return shutdownTerminate(false, id, timeout, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ShutdownComputeSystem shuts down a container by requesting a shutdown within
|
||||||
|
// the container operating system.
|
||||||
|
func ShutdownComputeSystem(id string, timeout uint32, context string) (uint32, error) {
|
||||||
|
return shutdownTerminate(true, id, timeout, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
// shutdownTerminate is a wrapper for ShutdownComputeSystem and TerminateComputeSystem
|
||||||
|
// which have very similar calling semantics
|
||||||
|
func shutdownTerminate(shutdown bool, id string, timeout uint32, context string) (uint32, error) {
|
||||||
|
|
||||||
|
var (
|
||||||
|
title = "HCSShim::"
|
||||||
|
procName string
|
||||||
|
)
|
||||||
|
if shutdown {
|
||||||
|
title = title + "ShutdownComputeSystem"
|
||||||
|
procName = procShutdownComputeSystem
|
||||||
|
} else {
|
||||||
|
title = title + "TerminateComputeSystem"
|
||||||
|
procName = procTerminateComputeSystem
|
||||||
|
}
|
||||||
|
logrus.Debugf(title+" id=%s context=%s", id, context)
|
||||||
|
|
||||||
|
// Load the DLL and get a handle to the procedure we need
|
||||||
|
dll, proc, err := loadAndFind(procName)
|
||||||
|
if dll != nil {
|
||||||
|
defer dll.Release()
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return 0xffffffff, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert id to uint16 pointers for calling the procedure
|
||||||
|
idp, err := syscall.UTF16PtrFromString(id)
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf(title+" - Failed conversion of id %s to pointer %s", id, err)
|
||||||
|
logrus.Error(err)
|
||||||
|
return 0xffffffff, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the procedure itself.
|
||||||
|
r1, _, err := proc.Call(
|
||||||
|
uintptr(unsafe.Pointer(idp)), uintptr(timeout))
|
||||||
|
|
||||||
|
use(unsafe.Pointer(idp))
|
||||||
|
|
||||||
|
if r1 != 0 {
|
||||||
|
err = fmt.Errorf(title+" - Win32 API call returned error r1=0x%X err=%s id=%s context=%s", r1, syscall.Errno(r1), id, context)
|
||||||
|
return uint32(r1), err
|
||||||
|
}
|
||||||
|
|
||||||
|
logrus.Debugf(title+" succeeded id=%s context=%s", id, context)
|
||||||
|
return 0, nil
|
||||||
|
}
|
|
@ -43,6 +43,6 @@ func StartComputeSystem(id string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
logrus.Debugf("HCSShim::StartComputeSystem - succeeded id=%s", id)
|
logrus.Debugf(title+" succeeded id=%s", id)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,49 +0,0 @@
|
||||||
package hcsshim
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
"github.com/Sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
// TerminateComputeSystem force terminates a container.
|
|
||||||
func TerminateComputeSystem(id string) error {
|
|
||||||
|
|
||||||
var title = "HCSShim::TerminateComputeSystem"
|
|
||||||
logrus.Debugf(title+" id=%s", id)
|
|
||||||
|
|
||||||
// Load the DLL and get a handle to the procedure we need
|
|
||||||
dll, proc, err := loadAndFind(procTerminateComputeSystem)
|
|
||||||
if dll != nil {
|
|
||||||
defer dll.Release()
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert id to uint16 pointers for calling the procedure
|
|
||||||
idp, err := syscall.UTF16PtrFromString(id)
|
|
||||||
if err != nil {
|
|
||||||
err = fmt.Errorf(title+" - Failed conversion of id %s to pointer %s", id, err)
|
|
||||||
logrus.Error(err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
timeout := uint32(0xffffffff)
|
|
||||||
|
|
||||||
// Call the procedure itself.
|
|
||||||
r1, _, err := proc.Call(
|
|
||||||
uintptr(unsafe.Pointer(idp)), uintptr(timeout))
|
|
||||||
|
|
||||||
use(unsafe.Pointer(idp))
|
|
||||||
|
|
||||||
if r1 != 0 {
|
|
||||||
err = fmt.Errorf(title+" - Win32 API call returned error r1=%d err=%s id=%s", r1, syscall.Errno(r1), id)
|
|
||||||
return syscall.Errno(r1)
|
|
||||||
}
|
|
||||||
|
|
||||||
logrus.Debugf(title+" - succeeded id=%s", id)
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -44,6 +44,6 @@ func TerminateProcessInComputeSystem(id string, processid uint32) (err error) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
logrus.Debugf(title+" - succeeded id=%s", id)
|
logrus.Debugf(title+" succeeded id=%s", id)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,6 +54,6 @@ func UnprepareLayer(info DriverInfo, layerId string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
logrus.Debugf(title+"- succeeded layerId=%s flavour=%d", layerId, info.Flavour)
|
logrus.Debugf(title+"succeeded flavour %d layerId=%s", info.Flavour, layerId)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,21 +9,19 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// WaitForProcessInComputeSystem waits for a process ID to terminate and returns
|
// WaitForProcessInComputeSystem waits for a process ID to terminate and returns
|
||||||
// the exit code.
|
// the exit code. Returns exitcode, errno, error
|
||||||
func WaitForProcessInComputeSystem(id string, processid uint32) (exitcode int32, err error) {
|
func WaitForProcessInComputeSystem(id string, processid uint32, timeout uint32) (int32, uint32, error) {
|
||||||
|
|
||||||
title := "HCSShim::WaitForProcessInComputeSystem"
|
title := "HCSShim::WaitForProcessInComputeSystem"
|
||||||
logrus.Debugf(title+" id=%s processid=%d", id, processid)
|
logrus.Debugf(title+" id=%s processid=%d", id, processid)
|
||||||
|
|
||||||
var timeout uint32 = 0xFFFFFFFF // (-1/INFINITE)
|
|
||||||
|
|
||||||
// Load the DLL and get a handle to the procedure we need
|
// Load the DLL and get a handle to the procedure we need
|
||||||
dll, proc, err := loadAndFind(procWaitForProcessInComputeSystem)
|
dll, proc, err := loadAndFind(procWaitForProcessInComputeSystem)
|
||||||
if dll != nil {
|
if dll != nil {
|
||||||
defer dll.Release()
|
defer dll.Release()
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert id to uint16 pointer for calling the procedure
|
// Convert id to uint16 pointer for calling the procedure
|
||||||
|
@ -31,7 +29,7 @@ func WaitForProcessInComputeSystem(id string, processid uint32) (exitcode int32,
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf(title+" - Failed conversion of id %s to pointer %s", id, err)
|
err = fmt.Errorf(title+" - Failed conversion of id %s to pointer %s", id, err)
|
||||||
logrus.Error(err)
|
logrus.Error(err)
|
||||||
return 0, err
|
return 0, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// To get a POINTER to the ExitCode
|
// To get a POINTER to the ExitCode
|
||||||
|
@ -47,10 +45,10 @@ func WaitForProcessInComputeSystem(id string, processid uint32) (exitcode int32,
|
||||||
use(unsafe.Pointer(idp))
|
use(unsafe.Pointer(idp))
|
||||||
|
|
||||||
if r1 != 0 {
|
if r1 != 0 {
|
||||||
err = fmt.Errorf(title+" - Win32 API call returned error r1=%d err=%s id=%s", r1, syscall.Errno(r1), id)
|
err = fmt.Errorf(title+" - Win32 API call returned error r1=0x%X err=%s id=%s", r1, syscall.Errno(r1), id)
|
||||||
return 0, err
|
return 0, uint32(r1), err
|
||||||
}
|
}
|
||||||
|
|
||||||
logrus.Debugf(title+" - succeeded id=%s processid=%d exitcode=%d", id, processid, *ec)
|
logrus.Debugf(title+" succeeded id=%s processid=%d exitcode=%d", id, processid, *ec)
|
||||||
return *ec, nil
|
return *ec, 0, nil
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче