Merge pull request #17285 from Microsoft/10662-exectp4workaround
Windows [TP4] Trap Hyper-V exec failure
This commit is contained in:
commit
fe1e04a84f
|
@ -51,8 +51,15 @@ func (d *Driver) Exec(c *execdriver.Command, processConfig *execdriver.ProcessCo
|
||||||
logrus.Debugln("commandLine: ", createProcessParms.CommandLine)
|
logrus.Debugln("commandLine: ", createProcessParms.CommandLine)
|
||||||
|
|
||||||
// Start the command running in the container.
|
// Start the command running in the container.
|
||||||
pid, stdin, stdout, stderr, err := hcsshim.CreateProcessInComputeSystem(c.ID, pipes.Stdin != nil, true, !processConfig.Tty, createProcessParms)
|
pid, stdin, stdout, stderr, rc, err := hcsshim.CreateProcessInComputeSystem(c.ID, pipes.Stdin != nil, true, !processConfig.Tty, createProcessParms)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// TODO Windows: TP4 Workaround. In Hyper-V containers, there is a limitation
|
||||||
|
// of one exec per container. This should be fixed post TP4. CreateProcessInComputeSystem
|
||||||
|
// will return a specific error which we handle here to give a good error message
|
||||||
|
// back to the user instead of an inactionable "An invalid argument was supplied"
|
||||||
|
if rc == hcsshim.Win32InvalidArgument {
|
||||||
|
return -1, fmt.Errorf("The limit of docker execs per Hyper-V container has been exceeded")
|
||||||
|
}
|
||||||
logrus.Errorf("CreateProcessInComputeSystem() failed %s", err)
|
logrus.Errorf("CreateProcessInComputeSystem() failed %s", err)
|
||||||
return -1, err
|
return -1, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -278,7 +278,7 @@ func (d *Driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, hooks execd
|
||||||
logrus.Debugf("CommandLine: %s", createProcessParms.CommandLine)
|
logrus.Debugf("CommandLine: %s", createProcessParms.CommandLine)
|
||||||
|
|
||||||
// Start the command running in the container.
|
// 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 {
|
if err != nil {
|
||||||
logrus.Errorf("CreateProcessInComputeSystem() failed %s", err)
|
logrus.Errorf("CreateProcessInComputeSystem() failed %s", err)
|
||||||
return execdriver.ExitStatus{ExitCode: -1}, err
|
return execdriver.ExitStatus{ExitCode: -1}, err
|
||||||
|
|
|
@ -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 325e531f8c49dd78580d5fd197ddb972fa4610e7
|
clone git github.com/microsoft/hcsshim de43b42b5ce14dfdcbeedb0628b0032174d89caa
|
||||||
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 github.com/vdemeester/shakers 3c10293ce22b900c27acad7b28656196fcc2f73b
|
clone git github.com/vdemeester/shakers 3c10293ce22b900c27acad7b28656196fcc2f73b
|
||||||
|
|
|
@ -67,7 +67,12 @@ func (p *pipe) Write(b []byte) (int, error) {
|
||||||
// CreateProcessInComputeSystem starts a process in a container. This is invoked, for example,
|
// CreateProcessInComputeSystem starts a process in a container. This is invoked, for example,
|
||||||
// as a result of docker run, docker exec, or RUN in Dockerfile. If successful,
|
// as a result of docker run, docker exec, or RUN in Dockerfile. If successful,
|
||||||
// it returns the PID of the process.
|
// it returns the PID of the process.
|
||||||
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) (uint32, io.WriteCloser, io.ReadCloser, io.ReadCloser, uint32, error) {
|
||||||
|
|
||||||
|
var (
|
||||||
|
stdin io.WriteCloser
|
||||||
|
stdout, stderr io.ReadCloser
|
||||||
|
)
|
||||||
|
|
||||||
title := "HCSShim::CreateProcessInComputeSystem"
|
title := "HCSShim::CreateProcessInComputeSystem"
|
||||||
logrus.Debugf(title+" id=%s", id)
|
logrus.Debugf(title+" id=%s", id)
|
||||||
|
@ -78,7 +83,7 @@ func CreateProcessInComputeSystem(id string, useStdin bool, useStdout bool, useS
|
||||||
defer dll.Release()
|
defer dll.Release()
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return 0, nil, nil, nil, 0xFFFFFFFF, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert id to uint16 pointer for calling the procedure
|
// Convert id to uint16 pointer for calling the procedure
|
||||||
|
@ -86,7 +91,7 @@ func CreateProcessInComputeSystem(id string, useStdin bool, useStdout bool, useS
|
||||||
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
|
return 0, nil, nil, nil, 0xFFFFFFFF, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we are not emulating a console, ignore any console size passed to us
|
// If we are not emulating a console, ignore any console size passed to us
|
||||||
|
@ -98,13 +103,13 @@ func CreateProcessInComputeSystem(id string, useStdin bool, useStdout bool, useS
|
||||||
paramsJson, err := json.Marshal(params)
|
paramsJson, err := json.Marshal(params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf(title+" - Failed to marshall params %v %s", params, err)
|
err = fmt.Errorf(title+" - Failed to marshall params %v %s", params, err)
|
||||||
return
|
return 0, nil, nil, nil, 0xFFFFFFFF, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert paramsJson to uint16 pointer for calling the procedure
|
// Convert paramsJson to uint16 pointer for calling the procedure
|
||||||
paramsJsonp, err := syscall.UTF16PtrFromString(string(paramsJson))
|
paramsJsonp, err := syscall.UTF16PtrFromString(string(paramsJson))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return 0, nil, nil, nil, 0xFFFFFFFF, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get a POINTER to variable to take the pid outparm
|
// Get a POINTER to variable to take the pid outparm
|
||||||
|
@ -138,8 +143,12 @@ func CreateProcessInComputeSystem(id string, useStdin bool, useStdout bool, useS
|
||||||
|
|
||||||
if r1 != 0 {
|
if r1 != 0 {
|
||||||
err = fmt.Errorf(title+" - Win32 API call returned error r1=%d err=%s id=%s params=%v", r1, syscall.Errno(r1), id, params)
|
err = fmt.Errorf(title+" - Win32 API call returned error r1=%d err=%s id=%s params=%v", r1, syscall.Errno(r1), id, params)
|
||||||
|
// Windows TP4: Hyper-V Containers may return this error with more than one
|
||||||
|
// concurrent exec. Do not log it as an error
|
||||||
|
if uint32(r1) != Win32InvalidArgument {
|
||||||
logrus.Error(err)
|
logrus.Error(err)
|
||||||
return
|
}
|
||||||
|
return 0, nil, nil, nil, uint32(r1), err
|
||||||
}
|
}
|
||||||
|
|
||||||
if useStdin {
|
if useStdin {
|
||||||
|
@ -153,5 +162,5 @@ func CreateProcessInComputeSystem(id string, useStdin bool, useStdout bool, useS
|
||||||
}
|
}
|
||||||
|
|
||||||
logrus.Debugf(title+" - succeeded id=%s params=%s pid=%d", id, paramsJson, *pid)
|
logrus.Debugf(title+" - succeeded id=%s params=%s pid=%d", id, paramsJson, *pid)
|
||||||
return *pid, stdin, stdout, stderr, nil
|
return *pid, stdin, stdout, stderr, 0, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,6 +55,7 @@ const (
|
||||||
Win32SystemShutdownIsInProgress = 0x8007045B // ShutdownComputeSystem: A system shutdown is in progress
|
Win32SystemShutdownIsInProgress = 0x8007045B // ShutdownComputeSystem: A system shutdown is in progress
|
||||||
Win32SpecifiedPathInvalid = 0x800700A1 // ShutdownComputeSystem: The specified path is invalid
|
Win32SpecifiedPathInvalid = 0x800700A1 // ShutdownComputeSystem: The specified path is invalid
|
||||||
Win32SystemCannotFindThePathSpecified = 0x80070003 // ShutdownComputeSystem: The system cannot find the path specified
|
Win32SystemCannotFindThePathSpecified = 0x80070003 // ShutdownComputeSystem: The system cannot find the path specified
|
||||||
|
Win32InvalidArgument = 0x80072726 // CreateProcessInComputeSystem: An invalid argument was supplied
|
||||||
|
|
||||||
// Timeout on wait calls
|
// Timeout on wait calls
|
||||||
TimeoutInfinite = 0xFFFFFFFF
|
TimeoutInfinite = 0xFFFFFFFF
|
||||||
|
|
Loading…
Reference in New Issue