From d4d8cc9c0a94840a2d45b549925301daa3bfcad3 Mon Sep 17 00:00:00 2001 From: Darren Stahl Date: Fri, 10 Jun 2016 15:27:05 -0700 Subject: [PATCH] Update vendored hcsshim to v0.3.4 Signed-off-by: Darren Stahl --- hack/vendor.sh | 2 +- .../github.com/Microsoft/hcsshim/callback.go | 26 +-- .../github.com/Microsoft/hcsshim/container.go | 151 +++++++----------- .../github.com/Microsoft/hcsshim/interface.go | 23 +++ .../github.com/Microsoft/hcsshim/process.go | 105 ++++++------ .../Microsoft/hcsshim/waithelper.go | 33 +++- 6 files changed, 175 insertions(+), 165 deletions(-) diff --git a/hack/vendor.sh b/hack/vendor.sh index bb194b64e9..a619a476ee 100755 --- a/hack/vendor.sh +++ b/hack/vendor.sh @@ -43,7 +43,7 @@ esac # the following lines are in sorted order, FYI clone git github.com/Azure/go-ansiterm 388960b655244e76e24c75f48631564eaefade62 -clone git github.com/Microsoft/hcsshim v0.3.2 +clone git github.com/Microsoft/hcsshim v0.3.4 clone git github.com/Microsoft/go-winio v0.3.4 clone git github.com/Sirupsen/logrus v0.10.0 # logrus is a common dependency among multiple deps clone git github.com/docker/libtrust 9cbd2a1374f46905c68a4eb3694a130610adc62a diff --git a/vendor/src/github.com/Microsoft/hcsshim/callback.go b/vendor/src/github.com/Microsoft/hcsshim/callback.go index 6812384e14..e8c2b00c8a 100644 --- a/vendor/src/github.com/Microsoft/hcsshim/callback.go +++ b/vendor/src/github.com/Microsoft/hcsshim/callback.go @@ -1,7 +1,6 @@ package hcsshim import ( - "errors" "sync" "syscall" ) @@ -26,14 +25,6 @@ var ( // Common notifications hcsNotificationInvalid hcsNotification = 0x00000000 hcsNotificationServiceDisconnect hcsNotification = 0x01000000 - - // ErrUnexpectedContainerExit is the error returned when a container exits while waiting for - // a different expected notification - ErrUnexpectedContainerExit = errors.New("unexpected container exit") - - // ErrUnexpectedProcessAbort is the error returned when communication with the compute service - // is lost while waiting for a notification - ErrUnexpectedProcessAbort = errors.New("lost communication with compute service") ) type hcsNotification uint32 @@ -58,6 +49,15 @@ func newChannels() notificationChannels { channels[hcsNotificationServiceDisconnect] = make(notificationChannel, 1) return channels } +func closeChannels(channels notificationChannels) { + close(channels[hcsNotificationSystemExited]) + close(channels[hcsNotificationSystemCreateCompleted]) + close(channels[hcsNotificationSystemStartCompleted]) + close(channels[hcsNotificationSystemPauseCompleted]) + close(channels[hcsNotificationSystemResumeCompleted]) + close(channels[hcsNotificationProcessExited]) + close(channels[hcsNotificationServiceDisconnect]) +} func notificationWatcher(notificationType hcsNotification, callbackNumber uintptr, notificationStatus uintptr, notificationData *uint16) uintptr { var result error @@ -66,10 +66,14 @@ func notificationWatcher(notificationType hcsNotification, callbackNumber uintpt } callbackMapLock.RLock() - channels := callbackMap[callbackNumber].channels + context := callbackMap[callbackNumber] callbackMapLock.RUnlock() - channels[notificationType] <- result + if context == nil { + return 0 + } + + context.channels[notificationType] <- result return 0 } diff --git a/vendor/src/github.com/Microsoft/hcsshim/container.go b/vendor/src/github.com/Microsoft/hcsshim/container.go index 4214be7474..6360347b00 100644 --- a/vendor/src/github.com/Microsoft/hcsshim/container.go +++ b/vendor/src/github.com/Microsoft/hcsshim/container.go @@ -13,11 +13,11 @@ import ( var ( defaultTimeout = time.Minute * 4 - - // ErrTimeout is an error encountered when waiting on a notification times out - ErrTimeout = errors.New("hcsshim: timeout waiting for notification") ) +const pendingUpdatesQuery = `{ "PropertyTypes" : ["PendingUpdates"]}` + +// ContainerError is an error encountered in HCS type ContainerError struct { Container *container Operation string @@ -71,9 +71,7 @@ func CreateContainer(id string, c *ContainerConfig) (Container, error) { if createError == nil || createError == ErrVmcomputeOperationPending { if err := container.registerCallback(); err != nil { - err := &ContainerError{Container: container, Operation: operation, Err: err} - logrus.Error(err) - return nil, err + return nil, makeContainerError(container, operation, "", err) } } } else { @@ -82,12 +80,7 @@ func CreateContainer(id string, c *ContainerConfig) (Container, error) { err = processAsyncHcsResult(createError, resultp, container.callbackNumber, hcsNotificationSystemCreateCompleted, &defaultTimeout) if err != nil { - if err == ErrTimeout || err == ErrUnexpectedProcessAbort || err == ErrUnexpectedContainerExit { - return nil, err - } - err := &ContainerError{Container: container, Operation: operation, ExtraInfo: configuration, Err: err} - logrus.Error(err) - return nil, err + return nil, makeContainerError(container, operation, configuration, err) } logrus.Debugf(title+" succeeded id=%s handle=%d", id, container.handle) @@ -112,9 +105,7 @@ func OpenContainer(id string) (Container, error) { err := hcsOpenComputeSystem(id, &handle, &resultp) err = processHcsResult(err, resultp) if err != nil { - err = &ContainerError{Container: container, Operation: operation, Err: err} - logrus.Error(err) - return nil, err + return nil, makeContainerError(container, operation, "", err) } container.handle = handle @@ -134,12 +125,7 @@ func (container *container) Start() error { err := hcsStartComputeSystemTP5(container.handle, nil, &resultp) err = processAsyncHcsResult(err, resultp, container.callbackNumber, hcsNotificationSystemStartCompleted, &defaultTimeout) if err != nil { - if err == ErrTimeout || err == ErrUnexpectedProcessAbort || err == ErrUnexpectedContainerExit { - return err - } - err := &ContainerError{Container: container, Operation: operation, Err: err} - logrus.Error(err) - return err + return makeContainerError(container, operation, "", err) } logrus.Debugf(title+" succeeded id=%s", container.id) @@ -160,9 +146,7 @@ func (container *container) Shutdown() error { if err == ErrVmcomputeOperationPending { return ErrVmcomputeOperationPending } - err = &ContainerError{Container: container, Operation: operation, Err: err} - logrus.Error(err) - return err + return makeContainerError(container, operation, "", err) } logrus.Debugf(title+" succeeded id=%s", container.id) @@ -183,9 +167,7 @@ func (container *container) Terminate() error { if err == ErrVmcomputeOperationPending { return ErrVmcomputeOperationPending } - err = &ContainerError{Container: container, Operation: operation, Err: err} - logrus.Error(err) - return err + return makeContainerError(container, operation, "", err) } logrus.Debugf(title+" succeeded id=%s", container.id) @@ -201,19 +183,12 @@ func (container *container) Wait() error { if hcsCallbacksSupported { err := waitForNotification(container.callbackNumber, hcsNotificationSystemExited, nil) if err != nil { - if err == ErrUnexpectedProcessAbort || err == ErrUnexpectedContainerExit { - return err - } - err := &ContainerError{Container: container, Operation: operation, Err: err} - logrus.Error(err) - return err + return makeContainerError(container, operation, "", err) } } else { _, err := container.waitTimeoutInternal(syscall.INFINITE) if err != nil { - err := &ContainerError{Container: container, Operation: operation, Err: err} - logrus.Error(err) - return err + return makeContainerError(container, operation, "", err) } } @@ -235,21 +210,14 @@ func (container *container) WaitTimeout(timeout time.Duration) error { if hcsCallbacksSupported { err := waitForNotification(container.callbackNumber, hcsNotificationSystemExited, &timeout) if err != nil { - if err == ErrTimeout || err == ErrUnexpectedProcessAbort || err == ErrUnexpectedContainerExit { - return err - } - err := &ContainerError{Container: container, Operation: operation, Err: err} - logrus.Error(err) - return err + return makeContainerError(container, operation, "", err) } } else { finished, err := waitTimeoutHelper(container, timeout) if !finished { return ErrTimeout } else if err != nil { - err := &ContainerError{Container: container, Operation: operation, Err: err} - logrus.Error(err) - return err + return makeContainerError(container, operation, "", err) } } @@ -273,12 +241,12 @@ func (container *container) hcsWait(timeout uint32) (bool, error) { return waitForSingleObject(exitEvent, timeout) } -func (container *container) properties() (*containerProperties, error) { +func (container *container) properties(query string) (*containerProperties, error) { var ( resultp *uint16 propertiesp *uint16 ) - err := hcsGetComputeSystemProperties(container.handle, "", &propertiesp, &resultp) + err := hcsGetComputeSystemProperties(container.handle, query, &propertiesp, &resultp) err = processHcsResult(err, resultp) if err != nil { return nil, err @@ -302,11 +270,9 @@ func (container *container) HasPendingUpdates() (bool, error) { operation := "HasPendingUpdates" title := "HCSShim::Container::" + operation logrus.Debugf(title+" id=%s", container.id) - properties, err := container.properties() + properties, err := container.properties(pendingUpdatesQuery) if err != nil { - err := &ContainerError{Container: container, Operation: operation, Err: err} - logrus.Error(err) - return false, err + return false, makeContainerError(container, operation, "", err) } logrus.Debugf(title+" succeeded id=%s", container.id) @@ -323,12 +289,7 @@ func (container *container) Pause() error { err := hcsPauseComputeSystemTP5(container.handle, nil, &resultp) err = processAsyncHcsResult(err, resultp, container.callbackNumber, hcsNotificationSystemPauseCompleted, &defaultTimeout) if err != nil { - if err == ErrTimeout || err == ErrUnexpectedProcessAbort || err == ErrUnexpectedContainerExit { - return err - } - err := &ContainerError{Container: container, Operation: operation, Err: err} - logrus.Error(err) - return err + return makeContainerError(container, operation, "", err) } logrus.Debugf(title+" succeeded id=%s", container.id) @@ -347,12 +308,7 @@ func (container *container) Resume() error { err := hcsResumeComputeSystemTP5(container.handle, nil, &resultp) err = processAsyncHcsResult(err, resultp, container.callbackNumber, hcsNotificationSystemResumeCompleted, &defaultTimeout) if err != nil { - if err == ErrTimeout || err == ErrUnexpectedProcessAbort || err == ErrUnexpectedContainerExit { - return err - } - err := &ContainerError{Container: container, Operation: operation, Err: err} - logrus.Error(err) - return err + return makeContainerError(container, operation, "", err) } logrus.Debugf(title+" succeeded id=%s", container.id) @@ -386,9 +342,7 @@ func (container *container) CreateProcess(c *ProcessConfig) (Process, error) { err = hcsCreateProcess(container.handle, configuration, &processInfo, &processHandle, &resultp) err = processHcsResult(err, resultp) if err != nil { - err = &ContainerError{Container: container, Operation: operation, ExtraInfo: configuration, Err: err} - logrus.Error(err) - return nil, err + return nil, makeContainerError(container, operation, configuration, err) } process := &process{ @@ -404,9 +358,7 @@ func (container *container) CreateProcess(c *ProcessConfig) (Process, error) { if hcsCallbacksSupported { if err := process.registerCallback(); err != nil { - err = &ContainerError{Container: container, Operation: operation, Err: err} - logrus.Error(err) - return nil, err + return nil, makeContainerError(container, operation, "", err) } } @@ -428,9 +380,7 @@ func (container *container) OpenProcess(pid int) (Process, error) { err := hcsOpenProcess(container.handle, uint32(pid), &processHandle, &resultp) err = processHcsResult(err, resultp) if err != nil { - err = &ContainerError{Container: container, Operation: operation, Err: err} - logrus.Error(err) - return nil, err + return nil, makeContainerError(container, operation, "", err) } process := &process{ @@ -440,9 +390,7 @@ func (container *container) OpenProcess(pid int) (Process, error) { } if err := process.registerCallback(); err != nil { - err = &ContainerError{Container: container, Operation: operation, Err: err} - logrus.Error(err) - return nil, err + return nil, makeContainerError(container, operation, "", err) } logrus.Debugf(title+" succeeded id=%s processid=%s", container.id, process.processID) @@ -463,16 +411,12 @@ func (container *container) Close() error { if hcsCallbacksSupported { if err := container.unregisterCallback(); err != nil { - err = &ContainerError{Container: container, Operation: operation, Err: err} - logrus.Error(err) - return err + return makeContainerError(container, operation, "", err) } } if err := hcsCloseComputeSystem(container.handle); err != nil { - err = &ContainerError{Container: container, Operation: operation, Err: err} - logrus.Error(err) - return err + return makeContainerError(container, operation, "", err) } container.handle = 0 @@ -487,16 +431,15 @@ func closeContainer(container *container) { } func (container *container) registerCallback() error { - callbackMapLock.Lock() - defer callbackMapLock.Unlock() - - callbackNumber := nextCallback - nextCallback++ - context := ¬ifcationWatcherContext{ channels: newChannels(), } + + callbackMapLock.Lock() + callbackNumber := nextCallback + nextCallback++ callbackMap[callbackNumber] = context + callbackMapLock.Unlock() var callbackHandle hcsCallback err := hcsRegisterComputeSystemCallback(container.handle, notificationWatcherCallback, callbackNumber, &callbackHandle) @@ -512,21 +455,32 @@ func (container *container) registerCallback() error { func (container *container) unregisterCallback() error { callbackNumber := container.callbackNumber - callbackMapLock.Lock() - defer callbackMapLock.Unlock() + callbackMapLock.RLock() + context := callbackMap[callbackNumber] + callbackMapLock.RUnlock() - handle := callbackMap[callbackNumber].handle + if context == nil { + return nil + } + + handle := context.handle if handle == 0 { return nil } + // hcsUnregisterComputeSystemCallback has its own syncronization + // to wait for all callbacks to complete. We must NOT hold the callbackMapLock. err := hcsUnregisterComputeSystemCallback(handle) if err != nil { return err } + closeChannels(context.channels) + + callbackMapLock.Lock() callbackMap[callbackNumber] = nil + callbackMapLock.Unlock() handle = 0 @@ -558,3 +512,20 @@ func (e *ContainerError) Error() string { return s } + +func makeContainerError(container *container, operation string, extraInfo string, err error) error { + // Don't wrap errors created in hcsshim + if err == ErrTimeout || + err == ErrUnexpectedProcessAbort || + err == ErrUnexpectedContainerExit || + err == ErrHandleClose || + err == ErrInvalidProcessState || + err == ErrInvalidNotificationType || + err == ErrVmcomputeOperationPending { + return err + } + + containerError := &ContainerError{Container: container, Operation: operation, ExtraInfo: extraInfo, Err: err} + logrus.Error(containerError) + return containerError +} diff --git a/vendor/src/github.com/Microsoft/hcsshim/interface.go b/vendor/src/github.com/Microsoft/hcsshim/interface.go index 881dc01431..c7f7cc8202 100644 --- a/vendor/src/github.com/Microsoft/hcsshim/interface.go +++ b/vendor/src/github.com/Microsoft/hcsshim/interface.go @@ -1,10 +1,33 @@ package hcsshim import ( + "errors" "io" "time" ) +var ( + // ErrInvalidNotificationType is an error encountered when an invalid notification type is used + ErrInvalidNotificationType = errors.New("hcsshim: invalid notification type") + + // ErrTimeout is an error encountered when waiting on a notification times out + ErrTimeout = errors.New("hcsshim: timeout waiting for notification") + + // ErrHandleClose is an error returned when the handle generating the notification being waited on has been closed + ErrHandleClose = errors.New("hcsshim: the handle generating this notification has been closed") + + // ErrInvalidProcessState is an error encountered when the process is not in a valid state for the requested operation + ErrInvalidProcessState = errors.New("the process is in an invalid state for the attempted operation") + + // ErrUnexpectedContainerExit is the error returned when a container exits while waiting for + // a different expected notification + ErrUnexpectedContainerExit = errors.New("unexpected container exit") + + // ErrUnexpectedProcessAbort is the error returned when communication with the compute service + // is lost while waiting for a notification + ErrUnexpectedProcessAbort = errors.New("lost communication with compute service") +) + // ProcessConfig is used as both the input of Container.CreateProcess // and to convert the parameters to JSON for passing onto the HCS type ProcessConfig struct { diff --git a/vendor/src/github.com/Microsoft/hcsshim/process.go b/vendor/src/github.com/Microsoft/hcsshim/process.go index 726e6e0112..07b9762dce 100644 --- a/vendor/src/github.com/Microsoft/hcsshim/process.go +++ b/vendor/src/github.com/Microsoft/hcsshim/process.go @@ -11,13 +11,10 @@ import ( "github.com/Sirupsen/logrus" ) -var ( - ErrInvalidProcessState = errors.New("the process is in an invalid state for the attempted operation") -) - type ProcessError struct { Process *process Operation string + ExtraInfo string Err error } @@ -85,9 +82,7 @@ func (process *process) Kill() error { if err == ErrVmcomputeOperationPending { return ErrVmcomputeOperationPending } else if err != nil { - err := &ProcessError{Operation: operation, Process: process, Err: err} - logrus.Error(err) - return err + return makeProcessError(process, operation, "", err) } logrus.Debugf(title+" succeeded processid=%d", process.processID) @@ -103,19 +98,12 @@ func (process *process) Wait() error { if hcsCallbacksSupported { err := waitForNotification(process.callbackNumber, hcsNotificationProcessExited, nil) if err != nil { - if err == ErrUnexpectedProcessAbort || err == ErrUnexpectedContainerExit { - return err - } - err := &ProcessError{Operation: operation, Process: process, Err: err} - logrus.Error(err) - return err + return makeProcessError(process, operation, "", err) } } else { _, err := process.waitTimeoutInternal(syscall.INFINITE) if err != nil { - err := &ProcessError{Operation: operation, Process: process, Err: err} - logrus.Error(err) - return err + return makeProcessError(process, operation, "", err) } } @@ -133,21 +121,14 @@ func (process *process) WaitTimeout(timeout time.Duration) error { if hcsCallbacksSupported { err := waitForNotification(process.callbackNumber, hcsNotificationProcessExited, &timeout) if err != nil { - if err == ErrTimeout || err == ErrUnexpectedProcessAbort || err == ErrUnexpectedContainerExit { - return err - } - err := &ProcessError{Operation: operation, Process: process, Err: err} - logrus.Error(err) - return err + return makeProcessError(process, operation, "", err) } } else { finished, err := waitTimeoutHelper(process, timeout) if !finished { return ErrTimeout } else if err != nil { - err := &ProcessError{Operation: operation, Process: process, Err: err} - logrus.Error(err) - return err + return makeProcessError(process, operation, "", err) } } @@ -183,9 +164,7 @@ func (process *process) ExitCode() (int, error) { properties, err := process.properties() if err != nil { - err := &ProcessError{Operation: operation, Process: process, Err: err} - logrus.Error(err) - return 0, err + return 0, makeProcessError(process, operation, "", err) } if properties.Exited == false { @@ -221,9 +200,7 @@ func (process *process) ResizeConsole(width, height uint16) error { err = hcsModifyProcess(process.handle, modifyRequestStr, &resultp) err = processHcsResult(err, resultp) if err != nil { - err := &ProcessError{Operation: operation, Process: process, Err: err} - logrus.Error(err) - return err + return makeProcessError(process, operation, "", err) } logrus.Debugf(title+" succeeded processid=%d", process.processID) @@ -242,9 +219,7 @@ func (process *process) properties() (*processStatus, error) { err := hcsGetProcessProperties(process.handle, &propertiesp, &resultp) err = processHcsResult(err, resultp) if err != nil { - err := &ProcessError{Operation: operation, Process: process, Err: err} - logrus.Error(err) - return nil, err + return nil, makeProcessError(process, operation, "", err) } if propertiesp == nil { @@ -279,9 +254,7 @@ func (process *process) Stdio() (io.WriteCloser, io.ReadCloser, io.ReadCloser, e err := hcsGetProcessInfo(process.handle, &processInfo, &resultp) err = processHcsResult(err, resultp) if err != nil { - err = &ProcessError{Operation: operation, Process: process, Err: err} - logrus.Error(err) - return nil, nil, nil, err + return nil, nil, nil, makeProcessError(process, operation, "", err) } stdIn, stdOut, stdErr = processInfo.StdInput, processInfo.StdOutput, processInfo.StdError @@ -327,9 +300,7 @@ func (process *process) CloseStdin() error { err = hcsModifyProcess(process.handle, modifyRequestStr, &resultp) err = processHcsResult(err, resultp) if err != nil { - err = &ProcessError{Operation: operation, Process: process, Err: err} - logrus.Error(err) - return err + return makeProcessError(process, operation, "", err) } logrus.Debugf(title+" succeeded processid=%d", process.processID) @@ -350,16 +321,12 @@ func (process *process) Close() error { if hcsCallbacksSupported { if err := process.unregisterCallback(); err != nil { - err = &ProcessError{Operation: operation, Process: process, Err: err} - logrus.Error(err) - return err + return makeProcessError(process, operation, "", err) } } if err := hcsCloseProcess(process.handle); err != nil { - err = &ProcessError{Operation: operation, Process: process, Err: err} - logrus.Error(err) - return err + return makeProcessError(process, operation, "", err) } process.handle = 0 @@ -374,16 +341,15 @@ func closeProcess(process *process) { } func (process *process) registerCallback() error { - callbackMapLock.Lock() - defer callbackMapLock.Unlock() - - callbackNumber := nextCallback - nextCallback++ - context := ¬ifcationWatcherContext{ channels: newChannels(), } + + callbackMapLock.Lock() + callbackNumber := nextCallback + nextCallback++ callbackMap[callbackNumber] = context + callbackMapLock.Unlock() var callbackHandle hcsCallback err := hcsRegisterProcessCallback(process.handle, notificationWatcherCallback, callbackNumber, &callbackHandle) @@ -399,20 +365,32 @@ func (process *process) registerCallback() error { func (process *process) unregisterCallback() error { callbackNumber := process.callbackNumber - callbackMapLock.Lock() - defer callbackMapLock.Unlock() - handle := callbackMap[callbackNumber].handle + callbackMapLock.RLock() + context := callbackMap[callbackNumber] + callbackMapLock.RUnlock() + + if context == nil { + return nil + } + + handle := context.handle if handle == 0 { return nil } + // hcsUnregisterProcessCallback has its own syncronization + // to wait for all callbacks to complete. We must NOT hold the callbackMapLock. err := hcsUnregisterProcessCallback(handle) if err != nil { return err } + closeChannels(context.channels) + + callbackMapLock.Lock() callbackMap[callbackNumber] = nil + callbackMapLock.Unlock() handle = 0 @@ -444,3 +422,20 @@ func (e *ProcessError) Error() string { return s } + +func makeProcessError(process *process, operation string, extraInfo string, err error) error { + // Don't wrap errors created in hcsshim + if err == ErrTimeout || + err == ErrUnexpectedProcessAbort || + err == ErrUnexpectedContainerExit || + err == ErrHandleClose || + err == ErrInvalidProcessState || + err == ErrInvalidNotificationType || + err == ErrVmcomputeOperationPending { + return err + } + + processError := &ProcessError{Process: process, Operation: operation, ExtraInfo: extraInfo, Err: err} + logrus.Error(processError) + return processError +} diff --git a/vendor/src/github.com/Microsoft/hcsshim/waithelper.go b/vendor/src/github.com/Microsoft/hcsshim/waithelper.go index d56798a5ee..3c3599a372 100644 --- a/vendor/src/github.com/Microsoft/hcsshim/waithelper.go +++ b/vendor/src/github.com/Microsoft/hcsshim/waithelper.go @@ -65,6 +65,7 @@ func waitForNotification(callbackNumber uintptr, expectedNotification hcsNotific expectedChannel := channels[expectedNotification] if expectedChannel == nil { logrus.Errorf("unknown notification type in waitForNotification %x", expectedNotification) + return ErrInvalidNotificationType } if timeout != nil { @@ -72,38 +73,54 @@ func waitForNotification(callbackNumber uintptr, expectedNotification hcsNotific defer timer.Stop() select { - case err := <-expectedChannel: + case err, ok := <-expectedChannel: + if !ok { + return ErrHandleClose + } return err - case err := <-channels[hcsNotificationSystemExited]: + case err, ok := <-channels[hcsNotificationSystemExited]: + if !ok { + return ErrHandleClose + } // If the expected notification is hcsNotificationSystemExited which of the two selects // chosen is random. Return the raw error if hcsNotificationSystemExited is expected if channels[hcsNotificationSystemExited] == expectedChannel { return err } return ErrUnexpectedContainerExit - case err := <-channels[hcsNotificationServiceDisconnect]: + case _, ok := <-channels[hcsNotificationServiceDisconnect]: + if !ok { + return ErrHandleClose + } // hcsNotificationServiceDisconnect should never be an expected notification // it does not need the same handling as hcsNotificationSystemExited - logrus.Error(err) return ErrUnexpectedProcessAbort case <-timer.C: return ErrTimeout } } select { - case err := <-expectedChannel: + case err, ok := <-expectedChannel: + if !ok { + return ErrHandleClose + } return err - case err := <-channels[hcsNotificationSystemExited]: + case err, ok := <-channels[hcsNotificationSystemExited]: + if !ok { + return ErrHandleClose + } // If the expected notification is hcsNotificationSystemExited which of the two selects // chosen is random. Return the raw error if hcsNotificationSystemExited is expected if channels[hcsNotificationSystemExited] == expectedChannel { return err } return ErrUnexpectedContainerExit - case err := <-channels[hcsNotificationServiceDisconnect]: + case _, ok := <-channels[hcsNotificationServiceDisconnect]: + if !ok { + return ErrHandleClose + } // hcsNotificationServiceDisconnect should never be an expected notification // it does not need the same handling as hcsNotificationSystemExited - logrus.Error(err) return ErrUnexpectedProcessAbort } }