Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added known error code when shutdown is already complete #51

Merged
merged 1 commit into from
Jun 15, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 1 addition & 54 deletions container.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ package hcsshim

import (
"encoding/json"
"errors"
"fmt"
"runtime"
"syscall"
"time"
Expand All @@ -17,14 +15,6 @@ var (

const pendingUpdatesQuery = `{ "PropertyTypes" : ["PendingUpdates"]}`

// ContainerError is an error encountered in HCS
type ContainerError struct {
Container *container
Operation string
ExtraInfo string
Err error
}

type container struct {
handle hcsSystem
id string
Expand Down Expand Up @@ -253,7 +243,7 @@ func (container *container) properties(query string) (*containerProperties, erro
}

if propertiesp == nil {
return nil, errors.New("Unexpected result from hcsGetComputeSystemProperties, properties should never be nil")
return nil, ErrUnexpectedValue
}
propertiesRaw := convertAndFreeCoTaskMemBytes(propertiesp)

Expand Down Expand Up @@ -486,46 +476,3 @@ func (container *container) unregisterCallback() error {

return nil
}

func (e *ContainerError) Error() string {
if e == nil {
return "<nil>"
}

if e.Container == nil {
return "unexpected nil container for error: " + e.Err.Error()
}

s := "container " + e.Container.id

if e.Operation != "" {
s += " encountered an error during " + e.Operation
}

if e.Err != nil {
s += fmt.Sprintf(" failed in Win32: %s (0x%x)", e.Err, win32FromError(e.Err))
}

if e.ExtraInfo != "" {
s += " extra info: " + e.ExtraInfo
}

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
}
149 changes: 149 additions & 0 deletions errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
package hcsshim

import (
"errors"
"fmt"
"syscall"

"github.com/Sirupsen/logrus"
)

var (
// 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")

// ErrInvalidNotificationType is an error encountered when an invalid notification type is used
ErrInvalidNotificationType = errors.New("hcsshim: invalid notification type")

// 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")

// ErrTimeout is an error encountered when waiting on a notification times out
ErrTimeout = errors.New("hcsshim: timeout waiting for notification")

// 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")

// ErrUnexpectedValue is an error returned when hcs returns an invalid value
ErrUnexpectedValue = errors.New("unexpected value returned from hcs")

// ErrVmcomputeAlreadyStopped is an error returned when a shutdown or terminate request is made on a stopped container
ErrVmcomputeAlreadyStopped = syscall.Errno(0xc0370110)

// ErrVmcomputeOperationPending is an error returned when the operation is being completed asynchronously
ErrVmcomputeOperationPending = syscall.Errno(0xC0370103)
)

// ProcessError is an error encountered in HCS during an operation on a Process object
type ProcessError struct {
Process *process
Operation string
ExtraInfo string
Err error
}

// ContainerError is an error encountered in HCS during an operation on a Container object
type ContainerError struct {
Container *container
Operation string
ExtraInfo string
Err error
}

func isKnownError(err error) bool {
// Don't wrap errors created in hcsshim
if err == ErrHandleClose ||
err == ErrInvalidNotificationType ||
err == ErrInvalidProcessState ||
err == ErrTimeout ||
err == ErrUnexpectedContainerExit ||
err == ErrUnexpectedProcessAbort ||
err == ErrUnexpectedValue ||
err == ErrVmcomputeAlreadyStopped ||
err == ErrVmcomputeOperationPending {
return true
}

return false
}

func (e *ContainerError) Error() string {
if e == nil {
return "<nil>"
}

if e.Container == nil {
return "unexpected nil container for error: " + e.Err.Error()
}

s := "container " + e.Container.id

if e.Operation != "" {
s += " encountered an error during " + e.Operation
}

if e.Err != nil {
s += fmt.Sprintf(" failed in Win32: %s (0x%x)", e.Err, win32FromError(e.Err))
}

if e.ExtraInfo != "" {
s += " extra info: " + e.ExtraInfo
}

return s
}

func makeContainerError(container *container, operation string, extraInfo string, err error) error {
// Return known errors to the client
if isKnownError(err) {
return err
}

// Log any unexpected errors
containerError := &ContainerError{Container: container, Operation: operation, ExtraInfo: extraInfo, Err: err}
logrus.Error(containerError)
return containerError
}

func (e *ProcessError) Error() string {
if e == nil {
return "<nil>"
}

if e.Process == nil {
return "Unexpected nil process for error: " + e.Err.Error()
}

s := fmt.Sprintf("process %d", e.Process.processID)

if e.Process.container != nil {
s += " in container " + e.Process.container.id
}

if e.Operation != "" {
s += " " + e.Operation
}

if e.Err != nil {
s += fmt.Sprintf(" failed in Win32: %s (0x%x)", e.Err, win32FromError(e.Err))
}

return s
}

func makeProcessError(process *process, operation string, extraInfo string, err error) error {
// Return known errors to the client
if isKnownError(err) {
return err
}

// Log any unexpected errors
processError := &ProcessError{Process: process, Operation: operation, ExtraInfo: extraInfo, Err: err}
logrus.Error(processError)
return processError
}
2 changes: 0 additions & 2 deletions hcsshim.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,6 @@ const (
ERROR_SHUTDOWN_IN_PROGRESS = syscall.Errno(1115)
WSAEINVAL = syscall.Errno(10022)

ErrVmcomputeOperationPending = syscall.Errno(0xC0370103)

// Timeout on wait calls
TimeoutInfinite = 0xFFFFFFFF
)
Expand Down
23 changes: 0 additions & 23 deletions interface.go
Original file line number Diff line number Diff line change
@@ -1,33 +1,10 @@
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 {
Expand Down
57 changes: 3 additions & 54 deletions process.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,14 @@ package hcsshim

import (
"encoding/json"
"errors"
"fmt"
"io"
"syscall"
"time"

"github.com/Sirupsen/logrus"
)

type ProcessError struct {
Process *process
Operation string
ExtraInfo string
Err error
}

// ContainerError is an error encountered in HCS
type process struct {
handle hcsProcess
processID int
Expand Down Expand Up @@ -48,7 +40,7 @@ type closeHandle struct {
}

type processStatus struct {
ProcessId uint32
ProcessID uint32
Exited bool
ExitCode uint32
LastWaitResult int32
Expand Down Expand Up @@ -223,7 +215,7 @@ func (process *process) properties() (*processStatus, error) {
}

if propertiesp == nil {
return nil, errors.New("Unexpected result from hcsGetProcessProperties, properties should never be nil")
return nil, ErrUnexpectedValue
}
propertiesRaw := convertAndFreeCoTaskMemBytes(propertiesp)

Expand Down Expand Up @@ -396,46 +388,3 @@ func (process *process) unregisterCallback() error {

return nil
}

func (e *ProcessError) Error() string {
if e == nil {
return "<nil>"
}

if e.Process == nil {
return "Unexpected nil process for error: " + e.Err.Error()
}

s := fmt.Sprintf("process %d", e.Process.processID)

if e.Process.container != nil {
s += " in container " + e.Process.container.id
}

if e.Operation != "" {
s += " " + e.Operation
}

if e.Err != nil {
s += fmt.Sprintf(" failed in Win32: %s (0x%x)", e.Err, win32FromError(e.Err))
}

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
}