Merge pull request #31 from thaJeztah/18.06-backport-jjh.37562
[18.06] backport "don't invoke HCS shutdown if terminate called"
diff --git a/libcontainerd/client_local_windows.go b/libcontainerd/client_local_windows.go
index 6e3454e..01435f3 100644
--- a/libcontainerd/client_local_windows.go
+++ b/libcontainerd/client_local_windows.go
@@ -42,18 +42,17 @@
// have access to the Spec
ociSpec *specs.Spec
- isWindows bool
- manualStopRequested bool
- hcsContainer hcsshim.Container
+ isWindows bool
+ hcsContainer hcsshim.Container
- id string
- status Status
- exitedAt time.Time
- exitCode uint32
- waitCh chan struct{}
- init *process
- execs map[string]*process
- updatePending bool
+ id string
+ status Status
+ exitedAt time.Time
+ exitCode uint32
+ waitCh chan struct{}
+ init *process
+ execs map[string]*process
+ terminateInvoked bool
}
// Win32 error codes that are used for various workarounds
@@ -324,15 +323,15 @@
logger.Debug("starting container")
if err = hcsContainer.Start(); err != nil {
c.logger.WithError(err).Error("failed to start container")
- ctr.debugGCS()
+ ctr.Lock()
if err := c.terminateContainer(ctr); err != nil {
c.logger.WithError(err).Error("failed to cleanup after a failed Start")
} else {
c.logger.Debug("cleaned up after failed Start by calling Terminate")
}
+ ctr.Unlock()
return err
}
- ctr.debugGCS()
c.Lock()
c.containers[id] = ctr
@@ -524,11 +523,13 @@
if err = hcsContainer.Start(); err != nil {
c.logger.WithError(err).Error("failed to start container")
ctr.debugGCS()
+ ctr.Lock()
if err := c.terminateContainer(ctr); err != nil {
c.logger.WithError(err).Error("failed to cleanup after a failed Start")
} else {
c.logger.Debug("cleaned up after failed Start by calling Terminate")
}
+ ctr.Unlock()
return err
}
ctr.debugGCS()
@@ -848,8 +849,6 @@
return err
}
- ctr.manualStopRequested = true
-
logger := c.logger.WithFields(logrus.Fields{
"container": containerID,
"process": processID,
@@ -861,11 +860,14 @@
if processID == InitProcessName {
if syscall.Signal(signal) == syscall.SIGKILL {
// Terminate the compute system
+ ctr.Lock()
+ ctr.terminateInvoked = true
if err := ctr.hcsContainer.Terminate(); err != nil {
if !hcsshim.IsPending(err) {
logger.WithError(err).Error("failed to terminate hccshim container")
}
}
+ ctr.Unlock()
} else {
// Shut down the container
if err := ctr.hcsContainer.Shutdown(); err != nil {
@@ -1167,12 +1169,17 @@
return ctr, p, nil
}
+// ctr mutex must be held when calling this function.
func (c *client) shutdownContainer(ctr *container) error {
- const shutdownTimeout = time.Minute * 5
- err := ctr.hcsContainer.Shutdown()
+ var err error
+ const waitTimeout = time.Minute * 5
- if hcsshim.IsPending(err) {
- err = ctr.hcsContainer.WaitTimeout(shutdownTimeout)
+ if !ctr.terminateInvoked {
+ err = ctr.hcsContainer.Shutdown()
+ }
+
+ if hcsshim.IsPending(err) || ctr.terminateInvoked {
+ err = ctr.hcsContainer.WaitTimeout(waitTimeout)
} else if hcsshim.IsAlreadyStopped(err) {
err = nil
}
@@ -1192,8 +1199,10 @@
return nil
}
+// ctr mutex must be held when calling this function.
func (c *client) terminateContainer(ctr *container) error {
const terminateTimeout = time.Minute * 5
+ ctr.terminateInvoked = true
err := ctr.hcsContainer.Terminate()
if hcsshim.IsPending(err) {
@@ -1259,7 +1268,6 @@
ctr.exitedAt = exitedAt
ctr.exitCode = uint32(exitCode)
close(ctr.waitCh)
- ctr.Unlock()
if err := c.shutdownContainer(ctr); err != nil {
exitCode = -1
@@ -1273,6 +1281,7 @@
} else {
logger.Debug("completed container shutdown")
}
+ ctr.Unlock()
if err := ctr.hcsContainer.Close(); err != nil {
exitCode = -1