Browse Source

Windows: [TP4] docker kill handling

Signed-off-by: John Howard <jhoward@microsoft.com>
John Howard 9 years ago
parent
commit
bc503ca8ab
26 changed files with 186 additions and 175 deletions
  1. 8 4
      daemon/execdriver/windows/exec.go
  2. 23 17
      daemon/execdriver/windows/run.go
  3. 20 18
      daemon/execdriver/windows/terminatekill.go
  4. 5 4
      daemon/execdriver/windows/windows.go
  5. 11 1
      daemon/kill.go
  6. 1 1
      hack/vendor.sh
  7. 10 0
      pkg/signal/signal.go
  8. 1 1
      vendor/src/github.com/microsoft/hcsshim/activatelayer.go
  9. 1 1
      vendor/src/github.com/microsoft/hcsshim/createlayer.go
  10. 2 2
      vendor/src/github.com/microsoft/hcsshim/createprocess.go
  11. 2 2
      vendor/src/github.com/microsoft/hcsshim/deactivatelayer.go
  12. 2 2
      vendor/src/github.com/microsoft/hcsshim/destroylayer.go
  13. 1 1
      vendor/src/github.com/microsoft/hcsshim/exportlayer.go
  14. 2 2
      vendor/src/github.com/microsoft/hcsshim/getlayermountpath.go
  15. 12 2
      vendor/src/github.com/microsoft/hcsshim/hcsshim.go
  16. 1 1
      vendor/src/github.com/microsoft/hcsshim/importlayer.go
  17. 2 2
      vendor/src/github.com/microsoft/hcsshim/layerexists.go
  18. 1 1
      vendor/src/github.com/microsoft/hcsshim/preparelayer.go
  19. 1 1
      vendor/src/github.com/microsoft/hcsshim/resizeconsole.go
  20. 0 50
      vendor/src/github.com/microsoft/hcsshim/shutdowncomputesystem.go
  21. 69 0
      vendor/src/github.com/microsoft/hcsshim/shutdownterminatecomputesystem.go
  22. 1 1
      vendor/src/github.com/microsoft/hcsshim/startcomputesystem.go
  23. 0 49
      vendor/src/github.com/microsoft/hcsshim/terminatecomputesystem.go
  24. 1 1
      vendor/src/github.com/microsoft/hcsshim/terminateprocess.go
  25. 1 1
      vendor/src/github.com/microsoft/hcsshim/unpreparelayer.go
  26. 8 10
      vendor/src/github.com/microsoft/hcsshim/waitprocess.go

+ 8 - 4
daemon/execdriver/windows/exec.go

@@ -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 {
-		logrus.Errorf("Failed to WaitForProcessInComputeSystem %s", err)
+	if exitCode, errno, err = hcsshim.WaitForProcessInComputeSystem(c.ID, pid, hcsshim.TimeoutInfinite); err != nil {
+		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() with ExitCode 0", c.ID)
+	logrus.Debugln("Exiting Run()", c.ID)
 	return int(exitCode), nil
 	return int(exitCode), nil
 }
 }

+ 23 - 17
daemon/execdriver/windows/run.go

@@ -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 terminateMode {
-			logrus.Debugf("Terminating container %s", c.ID)
-			if err := hcsshim.TerminateComputeSystem(c.ID); err != nil {
-				// 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)
+		if forceKill {
+			logrus.Debugf("Forcibly terminating container %s", c.ID)
+			if errno, err := hcsshim.TerminateComputeSystem(c.ID, hcsshim.TimeoutInfinite, "exec-run-defer"); err != nil {
+				logrus.Warnf("Ignoring error from TerminateComputeSystem 0x%X %s", errno, 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 {
-				// 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 ShutdownComputeSystem %s", err)
+			if errno, err := hcsshim.ShutdownComputeSystem(c.ID, hcsshim.TimeoutInfinite, "exec-run-defer"); err != nil {
+				if errno != hcsshim.Win32SystemShutdownIsInProgress &&
+					errno != hcsshim.Win32SpecifiedPathInvalid &&
+					errno != hcsshim.Win32SystemCannotFindThePathSpecified {
+					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
-	exitCode, err = hcsshim.WaitForProcessInComputeSystem(c.ID, pid)
+	var (
+		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)
-		return execdriver.ExitStatus{ExitCode: -1}, err
+		if errno != hcsshim.Win32PipeHasBeenEnded {
+			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)

+ 20 - 18
daemon/execdriver/windows/terminatekill.go

@@ -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)
+	return kill(p.ID, p.ContainerPid, syscall.SIGTERM)
 }
 }
 
 
 // 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)
+	return kill(p.ID, p.ContainerPid, syscall.Signal(sig))
 }
 }
 
 
-func kill(id string, pid int) error {
-	logrus.Debugln("kill() ", id, pid)
+func kill(id string, pid int, sig syscall.Signal) error {
+	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 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 {
+	if sig == syscall.SIGKILL || forceKill {
 		// Terminate the compute system
 		// Terminate the compute system
-		if err = hcsshim.TerminateComputeSystem(id); err != nil {
-			logrus.Errorf("Failed to terminate %s - %q", id, err)
+		if errno, err := hcsshim.TerminateComputeSystem(id, hcsshim.TimeoutInfinite, context); err != nil {
+			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 {
-			logrus.Errorf("Failed to shutdown %s - %q", id, err)
+		if errno, err := hcsshim.ShutdownComputeSystem(id, hcsshim.TimeoutInfinite, context); err != nil {
+			logrus.Errorf("Failed to shutdown %s - 0x%X %q", id, errno, err)
 		}
 		}
 	}
 	}
 	return err
 	return err

+ 5 - 4
daemon/execdriver/windows/windows.go

@@ -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
-				logrus.Warn("Using terminate mode in Windows exec driver. This is for testing purposes only.")
+				forceKill = true
+				logrus.Warn("Using force kill mode in Windows exec driver. This is for testing purposes only.")
 			}
 			}
 
 
 		default:
 		default:

+ 11 - 1
daemon/kill.go

@@ -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 {

+ 1 - 1
hack/vendor.sh

@@ -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

+ 10 - 0
pkg/signal/signal.go

@@ -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
+}

+ 1 - 1
vendor/src/github.com/microsoft/hcsshim/activatelayer.go

@@ -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)

+ 1 - 1
vendor/src/github.com/microsoft/hcsshim/createlayer.go

@@ -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)

+ 2 - 2
vendor/src/github.com/microsoft/hcsshim/createprocess.go

@@ -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

+ 2 - 2
vendor/src/github.com/microsoft/hcsshim/deactivatelayer.go

@@ -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
 }
 }

+ 2 - 2
vendor/src/github.com/microsoft/hcsshim/destroylayer.go

@@ -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
 }
 }

+ 1 - 1
vendor/src/github.com/microsoft/hcsshim/exportlayer.go

@@ -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
 }
 }

+ 2 - 2
vendor/src/github.com/microsoft/hcsshim/getlayermountpath.go

@@ -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
 }
 }

+ 12 - 2
vendor/src/github.com/microsoft/hcsshim/hcsshim.go

@@ -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)

+ 1 - 1
vendor/src/github.com/microsoft/hcsshim/importlayer.go

@@ -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
 }
 }

+ 2 - 2
vendor/src/github.com/microsoft/hcsshim/layerexists.go

@@ -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
 }
 }

+ 1 - 1
vendor/src/github.com/microsoft/hcsshim/preparelayer.go

@@ -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
 }
 }

+ 1 - 1
vendor/src/github.com/microsoft/hcsshim/resizeconsole.go

@@ -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
 
 
 }
 }

+ 0 - 50
vendor/src/github.com/microsoft/hcsshim/shutdowncomputesystem.go

@@ -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 - 0
vendor/src/github.com/microsoft/hcsshim/shutdownterminatecomputesystem.go

@@ -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
+}

+ 1 - 1
vendor/src/github.com/microsoft/hcsshim/startcomputesystem.go

@@ -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
 }
 }

+ 0 - 49
vendor/src/github.com/microsoft/hcsshim/terminatecomputesystem.go

@@ -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
-}

+ 1 - 1
vendor/src/github.com/microsoft/hcsshim/terminateprocess.go

@@ -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
 }
 }

+ 1 - 1
vendor/src/github.com/microsoft/hcsshim/unpreparelayer.go

@@ -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
 }
 }

+ 8 - 10
vendor/src/github.com/microsoft/hcsshim/waitprocess.go

@@ -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.
-func WaitForProcessInComputeSystem(id string, processid uint32) (exitcode int32, err error) {
+// the exit code. Returns exitcode, errno, 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)
-		return 0, err
+		err = fmt.Errorf(title+" - Win32 API call returned error r1=0x%X err=%s id=%s", r1, syscall.Errno(r1), id)
+		return 0, uint32(r1), err
 	}
 	}
 
 
-	logrus.Debugf(title+" - succeeded id=%s processid=%d exitcode=%d", id, processid, *ec)
-	return *ec, nil
+	logrus.Debugf(title+" succeeded id=%s processid=%d exitcode=%d", id, processid, *ec)
+	return *ec, 0, nil
 }
 }