|
@@ -9,6 +9,7 @@ import (
|
|
|
"path/filepath"
|
|
|
"strconv"
|
|
|
"strings"
|
|
|
+ "syscall"
|
|
|
"time"
|
|
|
|
|
|
"github.com/Microsoft/hcsshim"
|
|
@@ -20,6 +21,16 @@ import (
|
|
|
// preconfigured on the server.
|
|
|
const defaultContainerNAT = "ContainerNAT"
|
|
|
|
|
|
+// Win32 error codes that are used for various workarounds
|
|
|
+// These really should be ALL_CAPS to match golangs syscall library and standard
|
|
|
+// Win32 error conventions, but golint insists on CamelCase.
|
|
|
+const (
|
|
|
+ CoEClassstring = syscall.Errno(0x800401F3) // Invalid class string
|
|
|
+ ErrorNoNetwork = syscall.Errno(1222) // The network is not present or not started
|
|
|
+ ErrorBadPathname = syscall.Errno(161) // The specified path is invalid
|
|
|
+ ErrorInvalidObject = syscall.Errno(0x800710D8) // The object identifier does not represent a valid object
|
|
|
+)
|
|
|
+
|
|
|
type layer struct {
|
|
|
ID string
|
|
|
Path string
|
|
@@ -237,17 +248,19 @@ func (d *Driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, hooks execd
|
|
|
err = hcsshim.CreateComputeSystem(c.ID, configuration)
|
|
|
if err != nil {
|
|
|
if TP4RetryHack {
|
|
|
- if !strings.Contains(err.Error(), `Win32 API call returned error r1=0x800401f3`) && // Invalid class string
|
|
|
- !strings.Contains(err.Error(), `Win32 API call returned error r1=0x80070490`) && // Element not found
|
|
|
- !strings.Contains(err.Error(), `Win32 API call returned error r1=0x80070002`) && // The system cannot find the file specified
|
|
|
- !strings.Contains(err.Error(), `Win32 API call returned error r1=0x800704c6`) && // The network is not present or not started
|
|
|
- !strings.Contains(err.Error(), `Win32 API call returned error r1=0x800700a1`) && // The specified path is invalid
|
|
|
- !strings.Contains(err.Error(), `Win32 API call returned error r1=0x800710d8`) { // The object identifier does not represent a valid object
|
|
|
- logrus.Debugln("Failed to create temporary container ", err)
|
|
|
- return execdriver.ExitStatus{ExitCode: -1}, err
|
|
|
+ if herr, ok := err.(*hcsshim.HcsError); ok {
|
|
|
+ if herr.Err != syscall.ERROR_NOT_FOUND && // Element not found
|
|
|
+ herr.Err != syscall.ERROR_FILE_NOT_FOUND && // The system cannot find the file specified
|
|
|
+ herr.Err != ErrorNoNetwork && // The network is not present or not started
|
|
|
+ herr.Err != ErrorBadPathname && // The specified path is invalid
|
|
|
+ herr.Err != CoEClassstring && // Invalid class string
|
|
|
+ herr.Err != ErrorInvalidObject { // The object identifier does not represent a valid object
|
|
|
+ logrus.Debugln("Failed to create temporary container ", err)
|
|
|
+ return execdriver.ExitStatus{ExitCode: -1}, err
|
|
|
+ }
|
|
|
+ logrus.Warnf("Invoking Windows TP4 retry hack (%d of %d)", i, maxAttempts-1)
|
|
|
+ time.Sleep(50 * time.Millisecond)
|
|
|
}
|
|
|
- logrus.Warnf("Invoking Windows TP4 retry hack (%d of %d)", i, maxAttempts-1)
|
|
|
- time.Sleep(50 * time.Millisecond)
|
|
|
}
|
|
|
} else {
|
|
|
break
|
|
@@ -265,16 +278,17 @@ func (d *Driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, hooks execd
|
|
|
// Stop the container
|
|
|
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)
|
|
|
+ if err := hcsshim.TerminateComputeSystem(c.ID, hcsshim.TimeoutInfinite, "exec-run-defer"); err != nil {
|
|
|
+ logrus.Warnf("Ignoring error from TerminateComputeSystem %s", err)
|
|
|
}
|
|
|
} else {
|
|
|
logrus.Debugf("Shutting down container %s", c.ID)
|
|
|
- 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)
|
|
|
+ if err := hcsshim.ShutdownComputeSystem(c.ID, hcsshim.TimeoutInfinite, "exec-run-defer"); err != nil {
|
|
|
+ if herr, ok := err.(*hcsshim.HcsError); !ok ||
|
|
|
+ (herr.Err != hcsshim.ERROR_SHUTDOWN_IN_PROGRESS &&
|
|
|
+ herr.Err != ErrorBadPathname &&
|
|
|
+ herr.Err != syscall.ERROR_PATH_NOT_FOUND) {
|
|
|
+ logrus.Warnf("Ignoring error from ShutdownComputeSystem %s", err)
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -296,7 +310,7 @@ func (d *Driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, hooks execd
|
|
|
}
|
|
|
|
|
|
// Start the command running in the container.
|
|
|
- pid, stdin, stdout, stderr, _, err := hcsshim.CreateProcessInComputeSystem(c.ID, pipes.Stdin != nil, true, !c.ProcessConfig.Tty, createProcessParms)
|
|
|
+ pid, stdin, stdout, stderr, err := hcsshim.CreateProcessInComputeSystem(c.ID, pipes.Stdin != nil, true, !c.ProcessConfig.Tty, createProcessParms)
|
|
|
if err != nil {
|
|
|
logrus.Errorf("CreateProcessInComputeSystem() failed %s", err)
|
|
|
return execdriver.ExitStatus{ExitCode: -1}, err
|
|
@@ -333,13 +347,9 @@ func (d *Driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, hooks execd
|
|
|
hooks.Start(&c.ProcessConfig, int(pid), chOOM)
|
|
|
}
|
|
|
|
|
|
- var (
|
|
|
- exitCode int32
|
|
|
- errno uint32
|
|
|
- )
|
|
|
- exitCode, errno, err = hcsshim.WaitForProcessInComputeSystem(c.ID, pid, hcsshim.TimeoutInfinite)
|
|
|
+ exitCode, err := hcsshim.WaitForProcessInComputeSystem(c.ID, pid, hcsshim.TimeoutInfinite)
|
|
|
if err != nil {
|
|
|
- if errno != hcsshim.Win32PipeHasBeenEnded {
|
|
|
+ if herr, ok := err.(*hcsshim.HcsError); ok && herr.Err != syscall.ERROR_BROKEN_PIPE {
|
|
|
logrus.Warnf("WaitForProcessInComputeSystem failed (container may have been killed): %s", err)
|
|
|
}
|
|
|
// Do NOT return err here as the container would have
|