Signed-off-by: John Howard <jhoward@microsoft.com>
| ... | ... |
@@ -18,6 +18,7 @@ func (d *Driver) Exec(c *execdriver.Command, processConfig *execdriver.ProcessCo |
| 18 | 18 |
term execdriver.Terminal |
| 19 | 19 |
err error |
| 20 | 20 |
exitCode int32 |
| 21 |
+ errno uint32 |
|
| 21 | 22 |
) |
| 22 | 23 |
|
| 23 | 24 |
active := d.activeContainers[c.ID] |
| ... | ... |
@@ -77,12 +78,15 @@ func (d *Driver) Exec(c *execdriver.Command, processConfig *execdriver.ProcessCo |
| 77 | 77 |
hooks.Start(&c.ProcessConfig, int(pid), chOOM) |
| 78 | 78 |
} |
| 79 | 79 |
|
| 80 |
- if exitCode, err = hcsshim.WaitForProcessInComputeSystem(c.ID, pid); err != nil {
|
|
| 81 |
- logrus.Errorf("Failed to WaitForProcessInComputeSystem %s", err)
|
|
| 80 |
+ if exitCode, errno, err = hcsshim.WaitForProcessInComputeSystem(c.ID, pid, hcsshim.TimeoutInfinite); err != nil {
|
|
| 81 |
+ if errno == hcsshim.Win32PipeHasBeenEnded {
|
|
| 82 |
+ logrus.Debugf("Exiting Run() after WaitForProcessInComputeSystem failed with recognised error 0x%X", errno)
|
|
| 83 |
+ return hcsshim.WaitErrExecFailed, nil |
|
| 84 |
+ } |
|
| 85 |
+ logrus.Warnf("WaitForProcessInComputeSystem failed (container may have been killed): 0x%X %s", errno, err)
|
|
| 82 | 86 |
return -1, err |
| 83 | 87 |
} |
| 84 | 88 |
|
| 85 |
- // TODO Windows - Do something with this exit code |
|
| 86 |
- logrus.Debugln("Exiting Run() with ExitCode 0", c.ID)
|
|
| 89 |
+ logrus.Debugln("Exiting Run()", c.ID)
|
|
| 87 | 90 |
return int(exitCode), nil |
| 88 | 91 |
} |
| ... | ... |
@@ -220,22 +220,19 @@ func (d *Driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, hooks execd |
| 220 | 220 |
} |
| 221 | 221 |
defer func() {
|
| 222 | 222 |
// Stop the container |
| 223 |
- |
|
| 224 |
- if terminateMode {
|
|
| 225 |
- logrus.Debugf("Terminating container %s", c.ID)
|
|
| 226 |
- if err := hcsshim.TerminateComputeSystem(c.ID); err != nil {
|
|
| 227 |
- // IMPORTANT: Don't fail if fails to change state. It could already |
|
| 228 |
- // have been stopped through kill(). |
|
| 229 |
- // Otherwise, the docker daemon will hang in job wait() |
|
| 230 |
- logrus.Warnf("Ignoring error from TerminateComputeSystem %s", err)
|
|
| 223 |
+ if forceKill {
|
|
| 224 |
+ logrus.Debugf("Forcibly terminating container %s", c.ID)
|
|
| 225 |
+ if errno, err := hcsshim.TerminateComputeSystem(c.ID, hcsshim.TimeoutInfinite, "exec-run-defer"); err != nil {
|
|
| 226 |
+ logrus.Warnf("Ignoring error from TerminateComputeSystem 0x%X %s", errno, err)
|
|
| 231 | 227 |
} |
| 232 | 228 |
} else {
|
| 233 | 229 |
logrus.Debugf("Shutting down container %s", c.ID)
|
| 234 |
- if err := hcsshim.ShutdownComputeSystem(c.ID); err != nil {
|
|
| 235 |
- // IMPORTANT: Don't fail if fails to change state. It could already |
|
| 236 |
- // have been stopped through kill(). |
|
| 237 |
- // Otherwise, the docker daemon will hang in job wait() |
|
| 238 |
- logrus.Warnf("Ignoring error from ShutdownComputeSystem %s", err)
|
|
| 230 |
+ if errno, err := hcsshim.ShutdownComputeSystem(c.ID, hcsshim.TimeoutInfinite, "exec-run-defer"); err != nil {
|
|
| 231 |
+ if errno != hcsshim.Win32SystemShutdownIsInProgress && |
|
| 232 |
+ errno != hcsshim.Win32SpecifiedPathInvalid && |
|
| 233 |
+ errno != hcsshim.Win32SystemCannotFindThePathSpecified {
|
|
| 234 |
+ logrus.Warnf("Ignoring error from ShutdownComputeSystem 0x%X %s", errno, err)
|
|
| 235 |
+ } |
|
| 239 | 236 |
} |
| 240 | 237 |
} |
| 241 | 238 |
}() |
| ... | ... |
@@ -303,11 +300,20 @@ func (d *Driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, hooks execd |
| 303 | 303 |
hooks.Start(&c.ProcessConfig, int(pid), chOOM) |
| 304 | 304 |
} |
| 305 | 305 |
|
| 306 |
- var exitCode int32 |
|
| 307 |
- exitCode, err = hcsshim.WaitForProcessInComputeSystem(c.ID, pid) |
|
| 306 |
+ var ( |
|
| 307 |
+ exitCode int32 |
|
| 308 |
+ errno uint32 |
|
| 309 |
+ ) |
|
| 310 |
+ exitCode, errno, err = hcsshim.WaitForProcessInComputeSystem(c.ID, pid, hcsshim.TimeoutInfinite) |
|
| 308 | 311 |
if err != nil {
|
| 309 |
- logrus.Errorf("Failed to WaitForProcessInComputeSystem %s", err)
|
|
| 310 |
- return execdriver.ExitStatus{ExitCode: -1}, err
|
|
| 312 |
+ if errno != hcsshim.Win32PipeHasBeenEnded {
|
|
| 313 |
+ logrus.Warnf("WaitForProcessInComputeSystem failed (container may have been killed): %s", err)
|
|
| 314 |
+ } |
|
| 315 |
+ // Do NOT return err here as the container would have |
|
| 316 |
+ // started, otherwise docker will deadlock. It's perfectly legitimate |
|
| 317 |
+ // for WaitForProcessInComputeSystem to fail in situations such |
|
| 318 |
+ // as the container being killed on another thread. |
|
| 319 |
+ return execdriver.ExitStatus{ExitCode: hcsshim.WaitErrExecFailed}, nil
|
|
| 311 | 320 |
} |
| 312 | 321 |
|
| 313 | 322 |
logrus.Debugf("Exiting Run() exitCode %d id=%s", exitCode, c.ID)
|
| ... | ... |
@@ -3,6 +3,9 @@ |
| 3 | 3 |
package windows |
| 4 | 4 |
|
| 5 | 5 |
import ( |
| 6 |
+ "fmt" |
|
| 7 |
+ "syscall" |
|
| 8 |
+ |
|
| 6 | 9 |
"github.com/Sirupsen/logrus" |
| 7 | 10 |
"github.com/docker/docker/daemon/execdriver" |
| 8 | 11 |
"github.com/microsoft/hcsshim" |
| ... | ... |
@@ -10,37 +13,36 @@ import ( |
| 10 | 10 |
|
| 11 | 11 |
// Terminate implements the exec driver Driver interface. |
| 12 | 12 |
func (d *Driver) Terminate(p *execdriver.Command) error {
|
| 13 |
- logrus.Debugf("WindowsExec: Terminate() id=%s", p.ID)
|
|
| 14 |
- return kill(p.ID, p.ContainerPid) |
|
| 13 |
+ return kill(p.ID, p.ContainerPid, syscall.SIGTERM) |
|
| 15 | 14 |
} |
| 16 | 15 |
|
| 17 | 16 |
// Kill implements the exec driver Driver interface. |
| 18 | 17 |
func (d *Driver) Kill(p *execdriver.Command, sig int) error {
|
| 19 |
- logrus.Debugf("WindowsExec: Kill() id=%s sig=%d", p.ID, sig)
|
|
| 20 |
- return kill(p.ID, p.ContainerPid) |
|
| 18 |
+ return kill(p.ID, p.ContainerPid, syscall.Signal(sig)) |
|
| 21 | 19 |
} |
| 22 | 20 |
|
| 23 |
-func kill(id string, pid int) error {
|
|
| 24 |
- logrus.Debugln("kill() ", id, pid)
|
|
| 21 |
+func kill(id string, pid int, sig syscall.Signal) error {
|
|
| 22 |
+ logrus.Debugf("WindowsExec: kill() id=%s pid=%d sig=%d", id, pid, sig)
|
|
| 25 | 23 |
var err error |
| 24 |
+ context := fmt.Sprintf("kill: sig=%d pid=%d", sig, pid)
|
|
| 26 | 25 |
|
| 27 |
- // Terminate Process |
|
| 28 |
- if err = hcsshim.TerminateProcessInComputeSystem(id, uint32(pid)); err != nil {
|
|
| 29 |
- logrus.Warnf("Failed to terminate pid %d in %s: %q", pid, id, err)
|
|
| 30 |
- // Ignore errors |
|
| 31 |
- err = nil |
|
| 32 |
- } |
|
| 33 |
- |
|
| 34 |
- if terminateMode {
|
|
| 26 |
+ if sig == syscall.SIGKILL || forceKill {
|
|
| 35 | 27 |
// Terminate the compute system |
| 36 |
- if err = hcsshim.TerminateComputeSystem(id); err != nil {
|
|
| 37 |
- logrus.Errorf("Failed to terminate %s - %q", id, err)
|
|
| 28 |
+ if errno, err := hcsshim.TerminateComputeSystem(id, hcsshim.TimeoutInfinite, context); err != nil {
|
|
| 29 |
+ logrus.Errorf("Failed to terminate %s - 0x%X %q", id, errno, err)
|
|
| 38 | 30 |
} |
| 39 | 31 |
|
| 40 | 32 |
} else {
|
| 33 |
+ // Terminate Process |
|
| 34 |
+ if err = hcsshim.TerminateProcessInComputeSystem(id, uint32(pid)); err != nil {
|
|
| 35 |
+ logrus.Warnf("Failed to terminate pid %d in %s: %q", pid, id, err)
|
|
| 36 |
+ // Ignore errors |
|
| 37 |
+ err = nil |
|
| 38 |
+ } |
|
| 39 |
+ |
|
| 41 | 40 |
// Shutdown the compute system |
| 42 |
- if err = hcsshim.ShutdownComputeSystem(id); err != nil {
|
|
| 43 |
- logrus.Errorf("Failed to shutdown %s - %q", id, err)
|
|
| 41 |
+ if errno, err := hcsshim.ShutdownComputeSystem(id, hcsshim.TimeoutInfinite, context); err != nil {
|
|
| 42 |
+ logrus.Errorf("Failed to shutdown %s - 0x%X %q", id, errno, err)
|
|
| 44 | 43 |
} |
| 45 | 44 |
} |
| 46 | 45 |
return err |
| ... | ... |
@@ -18,7 +18,8 @@ import ( |
| 18 | 18 |
var dummyMode bool |
| 19 | 19 |
|
| 20 | 20 |
// This allows the daemon to terminate containers rather than shutdown |
| 21 |
-var terminateMode bool |
|
| 21 |
+// This allows the daemon to force kill (HCS terminate) rather than shutdown |
|
| 22 |
+var forceKill bool |
|
| 22 | 23 |
|
| 23 | 24 |
// Define name and version for windows |
| 24 | 25 |
var ( |
| ... | ... |
@@ -62,11 +63,11 @@ func NewDriver(root, initPath string, options []string) (*Driver, error) {
|
| 62 | 62 |
logrus.Warn("Using dummy mode in Windows exec driver. This is for development use only!")
|
| 63 | 63 |
} |
| 64 | 64 |
|
| 65 |
- case "terminate": |
|
| 65 |
+ case "forcekill": |
|
| 66 | 66 |
switch val {
|
| 67 | 67 |
case "1": |
| 68 |
- terminateMode = true |
|
| 69 |
- logrus.Warn("Using terminate mode in Windows exec driver. This is for testing purposes only.")
|
|
| 68 |
+ forceKill = true |
|
| 69 |
+ logrus.Warn("Using force kill mode in Windows exec driver. This is for testing purposes only.")
|
|
| 70 | 70 |
} |
| 71 | 71 |
|
| 72 | 72 |
default: |
| ... | ... |
@@ -1,6 +1,12 @@ |
| 1 | 1 |
package daemon |
| 2 | 2 |
|
| 3 |
-import "syscall" |
|
| 3 |
+import ( |
|
| 4 |
+ "fmt" |
|
| 5 |
+ "runtime" |
|
| 6 |
+ "syscall" |
|
| 7 |
+ |
|
| 8 |
+ "github.com/docker/docker/pkg/signal" |
|
| 9 |
+) |
|
| 4 | 10 |
|
| 5 | 11 |
// ContainerKill send signal to the container |
| 6 | 12 |
// 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 {
|
| 12 | 12 |
return err |
| 13 | 13 |
} |
| 14 | 14 |
|
| 15 |
+ if sig != 0 && !signal.ValidSignalForPlatform(syscall.Signal(sig)) {
|
|
| 16 |
+ return fmt.Errorf("The %s daemon does not support signal %d", runtime.GOOS, sig)
|
|
| 17 |
+ } |
|
| 18 |
+ |
|
| 15 | 19 |
// If no signal is passed, or SIGKILL, perform regular Kill (SIGKILL + wait()) |
| 16 | 20 |
if sig == 0 || syscall.Signal(sig) == syscall.SIGKILL {
|
| 17 | 21 |
if err := container.Kill(); err != nil {
|
| ... | ... |
@@ -14,7 +14,7 @@ clone git github.com/gorilla/context 14f550f51a |
| 14 | 14 |
clone git github.com/gorilla/mux e444e69cbd |
| 15 | 15 |
clone git github.com/kr/pty 5cf931ef8f |
| 16 | 16 |
clone git github.com/mattn/go-sqlite3 v1.1.0 |
| 17 |
-clone git github.com/microsoft/hcsshim 7f646aa6b26bcf90caee91e93cde4a80d0d8a83e |
|
| 17 |
+clone git github.com/microsoft/hcsshim 325e531f8c49dd78580d5fd197ddb972fa4610e7 |
|
| 18 | 18 |
clone git github.com/mistifyio/go-zfs v2.1.1 |
| 19 | 19 |
clone git github.com/tchap/go-patricia v2.1.0 |
| 20 | 20 |
clone git golang.org/x/net 3cffabab72adf04f8e3b01c5baf775361837b5fe https://github.com/golang/net.git |
| ... | ... |
@@ -42,3 +42,13 @@ func ParseSignal(rawSignal string) (syscall.Signal, error) {
|
| 42 | 42 |
} |
| 43 | 43 |
return signal, nil |
| 44 | 44 |
} |
| 45 |
+ |
|
| 46 |
+// ValidSignalForPlatform returns true if a signal is valid on the platform |
|
| 47 |
+func ValidSignalForPlatform(sig syscall.Signal) bool {
|
|
| 48 |
+ for _, v := range SignalMap {
|
|
| 49 |
+ if v == sig {
|
|
| 50 |
+ return true |
|
| 51 |
+ } |
|
| 52 |
+ } |
|
| 53 |
+ return false |
|
| 54 |
+} |
| ... | ... |
@@ -14,7 +14,7 @@ import ( |
| 14 | 14 |
// An activated layer must later be deactivated via DeactivateLayer. |
| 15 | 15 |
func ActivateLayer(info DriverInfo, id string) error {
|
| 16 | 16 |
title := "hcsshim::ActivateLayer " |
| 17 |
- logrus.Debugf(title+"Flavour %s ID %s", info.Flavour, id) |
|
| 17 |
+ logrus.Debugf(title+"Flavour %d ID %s", info.Flavour, id) |
|
| 18 | 18 |
|
| 19 | 19 |
// Load the DLL and get a handle to the procedure we need |
| 20 | 20 |
dll, proc, err := loadAndFind(procActivateLayer) |
| ... | ... |
@@ -12,7 +12,7 @@ import ( |
| 12 | 12 |
// the parent layer provided. |
| 13 | 13 |
func CreateLayer(info DriverInfo, id, parent string) error {
|
| 14 | 14 |
title := "hcsshim::CreateLayer " |
| 15 |
- logrus.Debugf(title+"Flavour %s ID %s parent %s", info.Flavour, id, parent) |
|
| 15 |
+ logrus.Debugf(title+"Flavour %d ID %s parent %s", info.Flavour, id, parent) |
|
| 16 | 16 |
|
| 17 | 17 |
// Load the DLL and get a handle to the procedure we need |
| 18 | 18 |
dll, proc, err := loadAndFind(procCreateLayer) |
| ... | ... |
@@ -70,7 +70,7 @@ func (p *pipe) Write(b []byte) (int, error) {
|
| 70 | 70 |
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) {
|
| 71 | 71 |
|
| 72 | 72 |
title := "HCSShim::CreateProcessInComputeSystem" |
| 73 |
- logrus.Debugf(title+"id=%s params=%s", id, params) |
|
| 73 |
+ logrus.Debugf(title+" id=%s", id) |
|
| 74 | 74 |
|
| 75 | 75 |
// Load the DLL and get a handle to the procedure we need |
| 76 | 76 |
dll, proc, err := loadAndFind(procCreateProcessWithStdHandlesInComputeSystem) |
| ... | ... |
@@ -110,7 +110,7 @@ func CreateProcessInComputeSystem(id string, useStdin bool, useStdout bool, useS |
| 110 | 110 |
// Get a POINTER to variable to take the pid outparm |
| 111 | 111 |
pid := new(uint32) |
| 112 | 112 |
|
| 113 |
- logrus.Debugf(title+" - Calling the procedure itself %s %s", id, paramsJson) |
|
| 113 |
+ logrus.Debugf(title+" - Calling Win32 %s %s", id, paramsJson) |
|
| 114 | 114 |
|
| 115 | 115 |
var stdinHandle, stdoutHandle, stderrHandle syscall.Handle |
| 116 | 116 |
var stdinParam, stdoutParam, stderrParam uintptr |
| ... | ... |
@@ -11,7 +11,7 @@ import ( |
| 11 | 11 |
// DeactivateLayer will dismount a layer that was mounted via ActivateLayer. |
| 12 | 12 |
func DeactivateLayer(info DriverInfo, id string) error {
|
| 13 | 13 |
title := "hcsshim::DeactivateLayer " |
| 14 |
- logrus.Debugf(title+"Flavour %s ID %s", info.Flavour, id) |
|
| 14 |
+ logrus.Debugf(title+"Flavour %d ID %s", info.Flavour, id) |
|
| 15 | 15 |
|
| 16 | 16 |
// Load the DLL and get a handle to the procedure we need |
| 17 | 17 |
dll, proc, err := loadAndFind(procDeactivateLayer) |
| ... | ... |
@@ -53,6 +53,6 @@ func DeactivateLayer(info DriverInfo, id string) error {
|
| 53 | 53 |
return err |
| 54 | 54 |
} |
| 55 | 55 |
|
| 56 |
- logrus.Debugf(title+" - succeeded id=%s flavour=%d", id, info.Flavour) |
|
| 56 |
+ logrus.Debugf(title+"succeeded flavour=%d id=%s", info.Flavour, id) |
|
| 57 | 57 |
return nil |
| 58 | 58 |
} |
| ... | ... |
@@ -12,7 +12,7 @@ import ( |
| 12 | 12 |
// id, including that layer's containing folder, if any. |
| 13 | 13 |
func DestroyLayer(info DriverInfo, id string) error {
|
| 14 | 14 |
title := "hcsshim::DestroyLayer " |
| 15 |
- logrus.Debugf(title+"Flavour %s ID %s", info.Flavour, id) |
|
| 15 |
+ logrus.Debugf(title+"Flavour %d ID %s", info.Flavour, id) |
|
| 16 | 16 |
|
| 17 | 17 |
// Load the DLL and get a handle to the procedure we need |
| 18 | 18 |
dll, proc, err := loadAndFind(procDestroyLayer) |
| ... | ... |
@@ -54,6 +54,6 @@ func DestroyLayer(info DriverInfo, id string) error {
|
| 54 | 54 |
return err |
| 55 | 55 |
} |
| 56 | 56 |
|
| 57 |
- logrus.Debugf(title+" - succeeded id=%s flavour=%d", id, info.Flavour) |
|
| 57 |
+ logrus.Debugf(title+"succeeded flavour=%d id=%s", info.Flavour, id) |
|
| 58 | 58 |
return nil |
| 59 | 59 |
} |
| ... | ... |
@@ -83,6 +83,6 @@ func ExportLayer(info DriverInfo, layerId string, exportFolderPath string, paren |
| 83 | 83 |
return err |
| 84 | 84 |
} |
| 85 | 85 |
|
| 86 |
- logrus.Debugf(title+"- succeeded layerId=%s flavour=%d folder=%s", layerId, info.Flavour, exportFolderPath) |
|
| 86 |
+ logrus.Debugf(title+"succeeded flavour=%d layerId=%s folder=%s", info.Flavour, layerId, exportFolderPath) |
|
| 87 | 87 |
return nil |
| 88 | 88 |
} |
| ... | ... |
@@ -14,7 +14,7 @@ import ( |
| 14 | 14 |
// folder path at which the layer is stored. |
| 15 | 15 |
func GetLayerMountPath(info DriverInfo, id string) (string, error) {
|
| 16 | 16 |
title := "hcsshim::GetLayerMountPath " |
| 17 |
- logrus.Debugf(title+"Flavour %s ID %s", info.Flavour, id) |
|
| 17 |
+ logrus.Debugf(title+"Flavour %d ID %s", info.Flavour, id) |
|
| 18 | 18 |
|
| 19 | 19 |
// Load the DLL and get a handle to the procedure we need |
| 20 | 20 |
dll, proc, err := loadAndFind(procGetLayerMountPath) |
| ... | ... |
@@ -86,6 +86,6 @@ func GetLayerMountPath(info DriverInfo, id string) (string, error) {
|
| 86 | 86 |
} |
| 87 | 87 |
|
| 88 | 88 |
path := syscall.UTF16ToString(mountPathp[0:]) |
| 89 |
- logrus.Debugf(title+" - succeeded id=%s flavour=%d path=%s", id, info.Flavour, path) |
|
| 89 |
+ logrus.Debugf(title+"succeeded flavour=%d id=%s path=%s", info.Flavour, id, path) |
|
| 90 | 90 |
return path, nil |
| 91 | 91 |
} |
| ... | ... |
@@ -46,6 +46,18 @@ const ( |
| 46 | 46 |
|
| 47 | 47 |
// Utility functions |
| 48 | 48 |
procCoTaskMemFree = "CoTaskMemFree" |
| 49 |
+ |
|
| 50 |
+ // Specific user-visible exit codes |
|
| 51 |
+ WaitErrExecFailed = 32767 |
|
| 52 |
+ |
|
| 53 |
+ // Known Win32 RC values which should be trapped |
|
| 54 |
+ Win32PipeHasBeenEnded = 0x8007006d // WaitForProcessInComputeSystem: The pipe has been ended |
|
| 55 |
+ Win32SystemShutdownIsInProgress = 0x8007045B // ShutdownComputeSystem: A system shutdown is in progress |
|
| 56 |
+ Win32SpecifiedPathInvalid = 0x800700A1 // ShutdownComputeSystem: The specified path is invalid |
|
| 57 |
+ Win32SystemCannotFindThePathSpecified = 0x80070003 // ShutdownComputeSystem: The system cannot find the path specified |
|
| 58 |
+ |
|
| 59 |
+ // Timeout on wait calls |
|
| 60 |
+ TimeoutInfinite = 0xFFFFFFFF |
|
| 49 | 61 |
) |
| 50 | 62 |
|
| 51 | 63 |
// loadAndFindFromDll finds a procedure in the given DLL. Note we do NOT do lazy loading as |
| ... | ... |
@@ -53,8 +65,6 @@ const ( |
| 53 | 53 |
// if a function can't be found. By explicitly loading, we can control error |
| 54 | 54 |
// handling gracefully without the daemon terminating. |
| 55 | 55 |
func loadAndFindFromDll(dllName, procedure string) (dll *syscall.DLL, proc *syscall.Proc, err error) {
|
| 56 |
- logrus.Debugf("hcsshim::loadAndFindFromDll %s %s", dllName, procedure)
|
|
| 57 |
- |
|
| 58 | 56 |
dll, err = syscall.LoadDLL(dllName) |
| 59 | 57 |
if err != nil {
|
| 60 | 58 |
err = fmt.Errorf("Failed to load %s - error %s", dllName, err)
|
| ... | ... |
@@ -82,6 +82,6 @@ func ImportLayer(info DriverInfo, layerId string, importFolderPath string, paren |
| 82 | 82 |
return err |
| 83 | 83 |
} |
| 84 | 84 |
|
| 85 |
- logrus.Debugf(title+"- succeeded layerId=%s flavour=%d folder=%s", layerId, info.Flavour, importFolderPath) |
|
| 85 |
+ logrus.Debugf(title+"succeeded flavour=%d layerId=%s folder=%s", info.Flavour, layerId, importFolderPath) |
|
| 86 | 86 |
return nil |
| 87 | 87 |
} |
| ... | ... |
@@ -12,7 +12,7 @@ import ( |
| 12 | 12 |
// to the system. |
| 13 | 13 |
func LayerExists(info DriverInfo, id string) (bool, error) {
|
| 14 | 14 |
title := "hcsshim::LayerExists " |
| 15 |
- logrus.Debugf(title+"Flavour %s ID %s", info.Flavour, id) |
|
| 15 |
+ logrus.Debugf(title+"Flavour %d ID %s", info.Flavour, id) |
|
| 16 | 16 |
|
| 17 | 17 |
// Load the DLL and get a handle to the procedure we need |
| 18 | 18 |
dll, proc, err := loadAndFind(procLayerExists) |
| ... | ... |
@@ -57,6 +57,6 @@ func LayerExists(info DriverInfo, id string) (bool, error) {
|
| 57 | 57 |
return false, err |
| 58 | 58 |
} |
| 59 | 59 |
|
| 60 |
- logrus.Debugf(title+" - succeeded id=%s flavour=%d exists=%d", id, info.Flavour, exists) |
|
| 60 |
+ logrus.Debugf(title+"succeeded flavour=%d id=%s exists=%d", info.Flavour, id, exists) |
|
| 61 | 61 |
return exists, nil |
| 62 | 62 |
} |
| ... | ... |
@@ -73,6 +73,6 @@ func PrepareLayer(info DriverInfo, layerId string, parentLayerPaths []string) er |
| 73 | 73 |
return err |
| 74 | 74 |
} |
| 75 | 75 |
|
| 76 |
- logrus.Debugf(title+"- succeeded layerId=%s flavour=%d", layerId, info.Flavour) |
|
| 76 |
+ logrus.Debugf(title+"succeeded flavour=%d layerId=%s", info.Flavour, layerId) |
|
| 77 | 77 |
return nil |
| 78 | 78 |
} |
| ... | ... |
@@ -42,7 +42,7 @@ func ResizeConsoleInComputeSystem(id string, processid uint32, h, w int) error {
|
| 42 | 42 |
return err |
| 43 | 43 |
} |
| 44 | 44 |
|
| 45 |
- logrus.Debugf(title+" - succeeded id=%s processid=%d (%d,%d)", id, processid, h, w) |
|
| 45 |
+ logrus.Debugf(title+" succeeded id=%s processid=%d (%d,%d)", id, processid, h, w) |
|
| 46 | 46 |
return nil |
| 47 | 47 |
|
| 48 | 48 |
} |
| 49 | 49 |
deleted file mode 100644 |
| ... | ... |
@@ -1,50 +0,0 @@ |
| 1 |
-package hcsshim |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "fmt" |
|
| 5 |
- "syscall" |
|
| 6 |
- "unsafe" |
|
| 7 |
- |
|
| 8 |
- "github.com/Sirupsen/logrus" |
|
| 9 |
-) |
|
| 10 |
- |
|
| 11 |
-// ShutdownComputeSystem shuts down a container by requesting a shutdown within |
|
| 12 |
-// the container operating system. |
|
| 13 |
-func ShutdownComputeSystem(id string) error {
|
|
| 14 |
- |
|
| 15 |
- var title = "HCSShim::ShutdownComputeSystem" |
|
| 16 |
- logrus.Debugf(title+" id=%s", id) |
|
| 17 |
- |
|
| 18 |
- // Load the DLL and get a handle to the procedure we need |
|
| 19 |
- dll, proc, err := loadAndFind(procShutdownComputeSystem) |
|
| 20 |
- if dll != nil {
|
|
| 21 |
- defer dll.Release() |
|
| 22 |
- } |
|
| 23 |
- if err != nil {
|
|
| 24 |
- return err |
|
| 25 |
- } |
|
| 26 |
- |
|
| 27 |
- // Convert id to uint16 pointers for calling the procedure |
|
| 28 |
- idp, err := syscall.UTF16PtrFromString(id) |
|
| 29 |
- if err != nil {
|
|
| 30 |
- err = fmt.Errorf(title+" - Failed conversion of id %s to pointer %s", id, err) |
|
| 31 |
- logrus.Error(err) |
|
| 32 |
- return err |
|
| 33 |
- } |
|
| 34 |
- |
|
| 35 |
- timeout := uint32(0xffffffff) |
|
| 36 |
- |
|
| 37 |
- // Call the procedure itself. |
|
| 38 |
- r1, _, err := proc.Call( |
|
| 39 |
- uintptr(unsafe.Pointer(idp)), uintptr(timeout)) |
|
| 40 |
- |
|
| 41 |
- use(unsafe.Pointer(idp)) |
|
| 42 |
- |
|
| 43 |
- if r1 != 0 {
|
|
| 44 |
- err = fmt.Errorf(title+" - Win32 API call returned error r1=%d err=%s id=%s", r1, syscall.Errno(r1), id) |
|
| 45 |
- return syscall.Errno(r1) |
|
| 46 |
- } |
|
| 47 |
- |
|
| 48 |
- logrus.Debugf(title+" - succeeded id=%s", id) |
|
| 49 |
- return nil |
|
| 50 |
-} |
| 51 | 1 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,69 @@ |
| 0 |
+package hcsshim |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "fmt" |
|
| 4 |
+ "syscall" |
|
| 5 |
+ "unsafe" |
|
| 6 |
+ |
|
| 7 |
+ "github.com/Sirupsen/logrus" |
|
| 8 |
+) |
|
| 9 |
+ |
|
| 10 |
+// TerminateComputeSystem force terminates a container. |
|
| 11 |
+func TerminateComputeSystem(id string, timeout uint32, context string) (uint32, error) {
|
|
| 12 |
+ return shutdownTerminate(false, id, timeout, context) |
|
| 13 |
+} |
|
| 14 |
+ |
|
| 15 |
+// ShutdownComputeSystem shuts down a container by requesting a shutdown within |
|
| 16 |
+// the container operating system. |
|
| 17 |
+func ShutdownComputeSystem(id string, timeout uint32, context string) (uint32, error) {
|
|
| 18 |
+ return shutdownTerminate(true, id, timeout, context) |
|
| 19 |
+} |
|
| 20 |
+ |
|
| 21 |
+// shutdownTerminate is a wrapper for ShutdownComputeSystem and TerminateComputeSystem |
|
| 22 |
+// which have very similar calling semantics |
|
| 23 |
+func shutdownTerminate(shutdown bool, id string, timeout uint32, context string) (uint32, error) {
|
|
| 24 |
+ |
|
| 25 |
+ var ( |
|
| 26 |
+ title = "HCSShim::" |
|
| 27 |
+ procName string |
|
| 28 |
+ ) |
|
| 29 |
+ if shutdown {
|
|
| 30 |
+ title = title + "ShutdownComputeSystem" |
|
| 31 |
+ procName = procShutdownComputeSystem |
|
| 32 |
+ } else {
|
|
| 33 |
+ title = title + "TerminateComputeSystem" |
|
| 34 |
+ procName = procTerminateComputeSystem |
|
| 35 |
+ } |
|
| 36 |
+ logrus.Debugf(title+" id=%s context=%s", id, context) |
|
| 37 |
+ |
|
| 38 |
+ // Load the DLL and get a handle to the procedure we need |
|
| 39 |
+ dll, proc, err := loadAndFind(procName) |
|
| 40 |
+ if dll != nil {
|
|
| 41 |
+ defer dll.Release() |
|
| 42 |
+ } |
|
| 43 |
+ if err != nil {
|
|
| 44 |
+ return 0xffffffff, err |
|
| 45 |
+ } |
|
| 46 |
+ |
|
| 47 |
+ // Convert id to uint16 pointers for calling the procedure |
|
| 48 |
+ idp, err := syscall.UTF16PtrFromString(id) |
|
| 49 |
+ if err != nil {
|
|
| 50 |
+ err = fmt.Errorf(title+" - Failed conversion of id %s to pointer %s", id, err) |
|
| 51 |
+ logrus.Error(err) |
|
| 52 |
+ return 0xffffffff, err |
|
| 53 |
+ } |
|
| 54 |
+ |
|
| 55 |
+ // Call the procedure itself. |
|
| 56 |
+ r1, _, err := proc.Call( |
|
| 57 |
+ uintptr(unsafe.Pointer(idp)), uintptr(timeout)) |
|
| 58 |
+ |
|
| 59 |
+ use(unsafe.Pointer(idp)) |
|
| 60 |
+ |
|
| 61 |
+ if r1 != 0 {
|
|
| 62 |
+ err = fmt.Errorf(title+" - Win32 API call returned error r1=0x%X err=%s id=%s context=%s", r1, syscall.Errno(r1), id, context) |
|
| 63 |
+ return uint32(r1), err |
|
| 64 |
+ } |
|
| 65 |
+ |
|
| 66 |
+ logrus.Debugf(title+" succeeded id=%s context=%s", id, context) |
|
| 67 |
+ return 0, nil |
|
| 68 |
+} |
| 49 | 49 |
deleted file mode 100644 |
| ... | ... |
@@ -1,49 +0,0 @@ |
| 1 |
-package hcsshim |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "fmt" |
|
| 5 |
- "syscall" |
|
| 6 |
- "unsafe" |
|
| 7 |
- |
|
| 8 |
- "github.com/Sirupsen/logrus" |
|
| 9 |
-) |
|
| 10 |
- |
|
| 11 |
-// TerminateComputeSystem force terminates a container. |
|
| 12 |
-func TerminateComputeSystem(id string) error {
|
|
| 13 |
- |
|
| 14 |
- var title = "HCSShim::TerminateComputeSystem" |
|
| 15 |
- logrus.Debugf(title+" id=%s", id) |
|
| 16 |
- |
|
| 17 |
- // Load the DLL and get a handle to the procedure we need |
|
| 18 |
- dll, proc, err := loadAndFind(procTerminateComputeSystem) |
|
| 19 |
- if dll != nil {
|
|
| 20 |
- defer dll.Release() |
|
| 21 |
- } |
|
| 22 |
- if err != nil {
|
|
| 23 |
- return err |
|
| 24 |
- } |
|
| 25 |
- |
|
| 26 |
- // Convert id to uint16 pointers for calling the procedure |
|
| 27 |
- idp, err := syscall.UTF16PtrFromString(id) |
|
| 28 |
- if err != nil {
|
|
| 29 |
- err = fmt.Errorf(title+" - Failed conversion of id %s to pointer %s", id, err) |
|
| 30 |
- logrus.Error(err) |
|
| 31 |
- return err |
|
| 32 |
- } |
|
| 33 |
- |
|
| 34 |
- timeout := uint32(0xffffffff) |
|
| 35 |
- |
|
| 36 |
- // Call the procedure itself. |
|
| 37 |
- r1, _, err := proc.Call( |
|
| 38 |
- uintptr(unsafe.Pointer(idp)), uintptr(timeout)) |
|
| 39 |
- |
|
| 40 |
- use(unsafe.Pointer(idp)) |
|
| 41 |
- |
|
| 42 |
- if r1 != 0 {
|
|
| 43 |
- err = fmt.Errorf(title+" - Win32 API call returned error r1=%d err=%s id=%s", r1, syscall.Errno(r1), id) |
|
| 44 |
- return syscall.Errno(r1) |
|
| 45 |
- } |
|
| 46 |
- |
|
| 47 |
- logrus.Debugf(title+" - succeeded id=%s", id) |
|
| 48 |
- return nil |
|
| 49 |
-} |
| ... | ... |
@@ -54,6 +54,6 @@ func UnprepareLayer(info DriverInfo, layerId string) error {
|
| 54 | 54 |
return err |
| 55 | 55 |
} |
| 56 | 56 |
|
| 57 |
- logrus.Debugf(title+"- succeeded layerId=%s flavour=%d", layerId, info.Flavour) |
|
| 57 |
+ logrus.Debugf(title+"succeeded flavour %d layerId=%s", info.Flavour, layerId) |
|
| 58 | 58 |
return nil |
| 59 | 59 |
} |
| ... | ... |
@@ -9,21 +9,19 @@ import ( |
| 9 | 9 |
) |
| 10 | 10 |
|
| 11 | 11 |
// WaitForProcessInComputeSystem waits for a process ID to terminate and returns |
| 12 |
-// the exit code. |
|
| 13 |
-func WaitForProcessInComputeSystem(id string, processid uint32) (exitcode int32, err error) {
|
|
| 12 |
+// the exit code. Returns exitcode, errno, error |
|
| 13 |
+func WaitForProcessInComputeSystem(id string, processid uint32, timeout uint32) (int32, uint32, error) {
|
|
| 14 | 14 |
|
| 15 | 15 |
title := "HCSShim::WaitForProcessInComputeSystem" |
| 16 | 16 |
logrus.Debugf(title+" id=%s processid=%d", id, processid) |
| 17 | 17 |
|
| 18 |
- var timeout uint32 = 0xFFFFFFFF // (-1/INFINITE) |
|
| 19 |
- |
|
| 20 | 18 |
// Load the DLL and get a handle to the procedure we need |
| 21 | 19 |
dll, proc, err := loadAndFind(procWaitForProcessInComputeSystem) |
| 22 | 20 |
if dll != nil {
|
| 23 | 21 |
defer dll.Release() |
| 24 | 22 |
} |
| 25 | 23 |
if err != nil {
|
| 26 |
- return 0, err |
|
| 24 |
+ return 0, 0, err |
|
| 27 | 25 |
} |
| 28 | 26 |
|
| 29 | 27 |
// Convert id to uint16 pointer for calling the procedure |
| ... | ... |
@@ -31,7 +29,7 @@ func WaitForProcessInComputeSystem(id string, processid uint32) (exitcode int32, |
| 31 | 31 |
if err != nil {
|
| 32 | 32 |
err = fmt.Errorf(title+" - Failed conversion of id %s to pointer %s", id, err) |
| 33 | 33 |
logrus.Error(err) |
| 34 |
- return 0, err |
|
| 34 |
+ return 0, 0, err |
|
| 35 | 35 |
} |
| 36 | 36 |
|
| 37 | 37 |
// To get a POINTER to the ExitCode |
| ... | ... |
@@ -47,10 +45,10 @@ func WaitForProcessInComputeSystem(id string, processid uint32) (exitcode int32, |
| 47 | 47 |
use(unsafe.Pointer(idp)) |
| 48 | 48 |
|
| 49 | 49 |
if r1 != 0 {
|
| 50 |
- err = fmt.Errorf(title+" - Win32 API call returned error r1=%d err=%s id=%s", r1, syscall.Errno(r1), id) |
|
| 51 |
- return 0, err |
|
| 50 |
+ err = fmt.Errorf(title+" - Win32 API call returned error r1=0x%X err=%s id=%s", r1, syscall.Errno(r1), id) |
|
| 51 |
+ return 0, uint32(r1), err |
|
| 52 | 52 |
} |
| 53 | 53 |
|
| 54 |
- logrus.Debugf(title+" - succeeded id=%s processid=%d exitcode=%d", id, processid, *ec) |
|
| 55 |
- return *ec, nil |
|
| 54 |
+ logrus.Debugf(title+" succeeded id=%s processid=%d exitcode=%d", id, processid, *ec) |
|
| 55 |
+ return *ec, 0, nil |
|
| 56 | 56 |
} |