From e70197ad1ccac8951651dc7c9c38e726425bcd8f Mon Sep 17 00:00:00 2001 From: John Starks Date: Fri, 18 May 2018 11:42:27 -0700 Subject: [PATCH] hcs: Include error events in errors --- errors.go | 17 ++-- internal/hcs/errors.go | 163 +++++++++++++++++++++++-------------- internal/hcs/hcs.go | 14 ---- internal/hcs/process.go | 48 +++++------ internal/hcs/system.go | 88 ++++++++++---------- internal/hcs/waithelper.go | 8 +- 6 files changed, 189 insertions(+), 149 deletions(-) diff --git a/errors.go b/errors.go index 3f176acc50..c97e06fcfd 100644 --- a/errors.go +++ b/errors.go @@ -96,6 +96,7 @@ type ProcessError struct { Operation string ExtraInfo string Err error + Events []hcs.ErrorEvent } // ContainerError is an error encountered in HCS during an operation on a Container object @@ -104,6 +105,7 @@ type ContainerError struct { Operation string ExtraInfo string Err error + Events []hcs.ErrorEvent } func (e *ContainerError) Error() string { @@ -130,6 +132,10 @@ func (e *ContainerError) Error() string { s += fmt.Sprintf(": %s", e.Err.Error()) } + for _, ev := range e.Events { + s += "\n" + ev.String() + } + if e.ExtraInfo != "" { s += " extra info: " + e.ExtraInfo } @@ -174,6 +180,10 @@ func (e *ProcessError) Error() string { s += fmt.Sprintf(": %s", e.Err.Error()) } + for _, ev := range e.Events { + s += "\n" + ev.String() + } + return s } @@ -210,14 +220,12 @@ func IsAlreadyClosed(err error) bool { // the requested operation is being completed in the background. func IsPending(err error) bool { return hcs.IsPending(getInnerError(err)) - } // IsTimeout returns a boolean indicating whether the error is caused by // a timeout waiting for the operation to complete. func IsTimeout(err error) bool { return hcs.IsTimeout(getInnerError(err)) - } // IsAlreadyStopped returns a boolean indicating whether the error is caused by @@ -227,7 +235,6 @@ func IsTimeout(err error) bool { // will currently return true when the error is ErrElementNotFound or ErrProcNotFound. func IsAlreadyStopped(err error) bool { return hcs.IsAlreadyStopped(getInnerError(err)) - } // IsNotSupported returns a boolean indicating whether the error is caused by @@ -253,14 +260,14 @@ func getInnerError(err error) error { func convertSystemError(err error, c *container) error { if serr, ok := err.(*hcs.SystemError); ok { - return &ContainerError{Container: c, Operation: serr.Operation, ExtraInfo: serr.ExtraInfo, Err: serr.Err} + return &ContainerError{Container: c, Operation: serr.Op, ExtraInfo: serr.Extra, Err: serr.Err, Events: serr.Events} } return err } func convertProcessError(err error, p *process) error { if perr, ok := err.(*hcs.ProcessError); ok { - return &ProcessError{Process: p, Operation: perr.Operation, ExtraInfo: perr.ExtraInfo, Err: perr.Err} + return &ProcessError{Process: p, Operation: perr.Op, Err: perr.Err, Events: perr.Events} } return err } diff --git a/internal/hcs/errors.go b/internal/hcs/errors.go index 9d3743408e..caa18dcd2a 100644 --- a/internal/hcs/errors.go +++ b/internal/hcs/errors.go @@ -1,11 +1,13 @@ package hcs import ( + "encoding/json" "errors" "fmt" "syscall" - "github.com/Microsoft/hcsshim/internal/hcserror" + "github.com/Microsoft/hcsshim/internal/interop" + "github.com/sirupsen/logrus" ) var ( @@ -74,93 +76,134 @@ var ( ErrPlatformNotSupported = errors.New("unsupported platform request") ) -// ProcessError is an error encountered in HCS during an operation on a Process object -type ProcessError struct { - SystemID string - PID int - Operation string - ExtraInfo string - Err error +type ErrorEvent struct { + Message string `json:"Message,omitempty"` // Fully formated error message + StackTrace string `json:"StackTrace,omitempty"` // Stack trace in string form + Provider string `json:"Provider,omitempty"` + EventID uint16 `json:"EventId,omitempty"` + Flags uint32 `json:"Flags,omitempty"` + Source string `json:"Source,omitempty"` + //Data []EventData `json:"Data,omitempty"` // Omit this as HCS doesn't encode this well. It's more confusing to include. It is however logged in debug mode (see processHcsResult function) } -// SystemError is an error encountered in HCS during an operation on a Container object -type SystemError struct { - ID string - Operation string - ExtraInfo string - Err error +type hcsResult struct { + Error int32 + ErrorMessage string + ErrorEvents []ErrorEvent `json:"ErrorEvents,omitempty"` } -func (e *SystemError) Error() string { - if e == nil { - return "" +func (ev *ErrorEvent) String() string { + evs := "[Event Detail: " + ev.Message + if ev.StackTrace != "" { + evs += " Stack Trace: " + ev.StackTrace } - - s := "system " + e.ID - - if e.Operation != "" { - s += " encountered an error during " + e.Operation + if ev.Provider != "" { + evs += " Provider: " + ev.Provider } - - switch e.Err.(type) { - case nil: - break - case syscall.Errno: - s += fmt.Sprintf(": failure in a Windows system call: %s (0x%x)", e.Err, hcserror.Win32FromError(e.Err)) - default: - s += fmt.Sprintf(": %s", e.Err.Error()) + if ev.EventID != 0 { + evs = fmt.Sprintf("%s EventID: %d", evs, ev.EventID) + } + if ev.Flags != 0 { + evs = fmt.Sprintf("%s flags: %d", evs, ev.Flags) } + if ev.Source != "" { + evs += " Source: " + ev.Source + } + evs += "]" + return evs +} - if e.ExtraInfo != "" { - s += " extra info: " + e.ExtraInfo +func processHcsResult(resultp *uint16) []ErrorEvent { + if resultp != nil { + resultj := interop.ConvertAndFreeCoTaskMemString(resultp) + logrus.Debugf("Result: %s", resultj) + result := &hcsResult{} + if err := json.Unmarshal([]byte(resultj), result); err != nil { + logrus.Warnf("Could not unmarshal HCS result %s: %s", resultj, err) + return nil + } + return result.ErrorEvents } + return nil +} - return s +type HcsError struct { + Op string + Err error + Events []ErrorEvent } -func makeSystemError(system *System, operation string, extraInfo string, err error) error { - // Don't double wrap errors - if _, ok := err.(*SystemError); ok { - return err +func (e *HcsError) Error() string { + s := e.Op + ": " + e.Err.Error() + for _, ev := range e.Events { + s += "\n" + ev.String() } - serr := &SystemError{ID: system.ID, Operation: operation, ExtraInfo: extraInfo, Err: err} - return serr + return s } -func (e *ProcessError) Error() string { - if e == nil { - return "" - } +// ProcessError is an error encountered in HCS during an operation on a Process object +type ProcessError struct { + SystemID string + PID int + Op string + Err error + Events []ErrorEvent +} - s := fmt.Sprintf("process %d", e.PID) +// SystemError is an error encountered in HCS during an operation on a Container object +type SystemError struct { + ID string + Op string + Err error + Extra string + Events []ErrorEvent +} - if e.SystemID != "" { - s += " in container " + e.SystemID +func (e *SystemError) Error() string { + s := e.Op + " " + e.ID + ": " + e.Err.Error() + for _, ev := range e.Events { + s += "\n" + ev.String() } - - if e.Operation != "" { - s += " encountered an error during " + e.Operation + if e.Extra != "" { + s += "\n(extra info: " + e.Extra + ")" } + return s +} - switch e.Err.(type) { - case nil: - break - case syscall.Errno: - s += fmt.Sprintf(": failure in a Windows system call: %s (0x%x)", e.Err, hcserror.Win32FromError(e.Err)) - default: - s += fmt.Sprintf(": %s", e.Err.Error()) +func makeSystemError(system *System, op string, extra string, err error, events []ErrorEvent) error { + // Don't double wrap errors + if _, ok := err.(*SystemError); ok { + return err + } + return &SystemError{ + ID: system.ID, + Op: op, + Extra: extra, + Err: err, + Events: events, } +} +func (e *ProcessError) Error() string { + s := fmt.Sprintf("%s %s:%d: %s", e.Op, e.SystemID, e.PID, e.Err.Error()) + for _, ev := range e.Events { + s += "\n" + ev.String() + } return s } -func makeProcessError(process *Process, operation string, extraInfo string, err error) error { +func makeProcessError(process *Process, op string, err error, events []ErrorEvent) error { // Don't double wrap errors if _, ok := err.(*ProcessError); ok { return err } - processError := &ProcessError{PID: process.processID, SystemID: process.system.ID, Operation: operation, ExtraInfo: extraInfo, Err: err} - return processError + return &ProcessError{ + PID: process.processID, + SystemID: process.system.ID, + Op: op, + Err: err, + Events: events, + } } // IsNotExist checks if an error is caused by the Container or Process not existing. @@ -225,6 +268,8 @@ func getInnerError(err error) error { switch pe := err.(type) { case nil: return nil + case *HcsError: + err = pe.Err case *SystemError: err = pe.Err case *ProcessError: diff --git a/internal/hcs/hcs.go b/internal/hcs/hcs.go index e3f2a2168d..b8e30eba17 100644 --- a/internal/hcs/hcs.go +++ b/internal/hcs/hcs.go @@ -5,10 +5,6 @@ package hcs import ( "syscall" - - "github.com/Microsoft/hcsshim/internal/hcserror" - "github.com/Microsoft/hcsshim/internal/interop" - "github.com/sirupsen/logrus" ) //go:generate go run ../../mksyscall_windows.go -output zsyscall_windows.go hcs.go @@ -38,8 +34,6 @@ import ( //sys hcsRegisterProcessCallback(process hcsProcess, callback uintptr, context uintptr, callbackHandle *hcsCallback) (hr error) = vmcompute.HcsRegisterProcessCallback? //sys hcsUnregisterProcessCallback(callbackHandle hcsCallback) (hr error) = vmcompute.HcsUnregisterProcessCallback? -type HcsError = hcserror.HcsError - type hcsSystem syscall.Handle type hcsProcess syscall.Handle type hcsCallback syscall.Handle @@ -51,11 +45,3 @@ type hcsProcessInformation struct { StdOutput syscall.Handle StdError syscall.Handle } - -func processHcsResult(err error, resultp *uint16) error { - if resultp != nil { - result := interop.ConvertAndFreeCoTaskMemString(resultp) - logrus.Debugf("Result: %s", result) - } - return err -} diff --git a/internal/hcs/process.go b/internal/hcs/process.go index 04b60c5819..99d50ca090 100644 --- a/internal/hcs/process.go +++ b/internal/hcs/process.go @@ -74,14 +74,14 @@ func (process *Process) Kill() error { logrus.Debugf(title+" processid=%d", process.processID) if process.handle == 0 { - return makeProcessError(process, operation, "", ErrAlreadyClosed) + return makeProcessError(process, operation, ErrAlreadyClosed, nil) } var resultp *uint16 err := hcsTerminateProcess(process.handle, &resultp) - err = processHcsResult(err, resultp) + events := processHcsResult(resultp) if err != nil { - return makeProcessError(process, operation, "", err) + return makeProcessError(process, operation, err, events) } logrus.Debugf(title+" succeeded processid=%d", process.processID) @@ -96,7 +96,7 @@ func (process *Process) Wait() error { err := waitForNotification(process.callbackNumber, hcsNotificationProcessExited, nil) if err != nil { - return makeProcessError(process, operation, "", err) + return makeProcessError(process, operation, err, nil) } logrus.Debugf(title+" succeeded processid=%d", process.processID) @@ -112,7 +112,7 @@ func (process *Process) WaitTimeout(timeout time.Duration) error { err := waitForNotification(process.callbackNumber, hcsNotificationProcessExited, &timeout) if err != nil { - return makeProcessError(process, operation, "", err) + return makeProcessError(process, operation, err, nil) } logrus.Debugf(title+" succeeded processid=%d", process.processID) @@ -128,7 +128,7 @@ func (process *Process) ResizeConsole(width, height uint16) error { logrus.Debugf(title+" processid=%d", process.processID) if process.handle == 0 { - return makeProcessError(process, operation, "", ErrAlreadyClosed) + return makeProcessError(process, operation, ErrAlreadyClosed, nil) } modifyRequest := processModifyRequest{ @@ -148,9 +148,9 @@ func (process *Process) ResizeConsole(width, height uint16) error { var resultp *uint16 err = hcsModifyProcess(process.handle, modifyRequestStr, &resultp) - err = processHcsResult(err, resultp) + events := processHcsResult(resultp) if err != nil { - return makeProcessError(process, operation, "", err) + return makeProcessError(process, operation, err, events) } logrus.Debugf(title+" succeeded processid=%d", process.processID) @@ -165,7 +165,7 @@ func (process *Process) Properties() (*ProcessStatus, error) { logrus.Debugf(title+" processid=%d", process.processID) if process.handle == 0 { - return nil, makeProcessError(process, operation, "", ErrAlreadyClosed) + return nil, makeProcessError(process, operation, ErrAlreadyClosed, nil) } var ( @@ -173,9 +173,9 @@ func (process *Process) Properties() (*ProcessStatus, error) { propertiesp *uint16 ) err := hcsGetProcessProperties(process.handle, &propertiesp, &resultp) - err = processHcsResult(err, resultp) + events := processHcsResult(resultp) if err != nil { - return nil, err + return nil, makeProcessError(process, operation, err, events) } if propertiesp == nil { @@ -185,7 +185,7 @@ func (process *Process) Properties() (*ProcessStatus, error) { properties := &ProcessStatus{} if err := json.Unmarshal(propertiesRaw, properties); err != nil { - return nil, err + return nil, makeProcessError(process, operation, err, nil) } logrus.Debugf(title+" succeeded processid=%d, properties=%s", process.processID, propertiesRaw) @@ -198,15 +198,15 @@ func (process *Process) ExitCode() (int, error) { operation := "ExitCode" properties, err := process.Properties() if err != nil { - return 0, makeProcessError(process, operation, "", err) + return 0, makeProcessError(process, operation, err, nil) } if properties.Exited == false { - return 0, makeProcessError(process, operation, "", ErrInvalidProcessState) + return 0, makeProcessError(process, operation, ErrInvalidProcessState, nil) } if properties.LastWaitResult != 0 { - return 0, makeProcessError(process, operation, "", syscall.Errno(properties.LastWaitResult)) + return 0, makeProcessError(process, operation, syscall.Errno(properties.LastWaitResult), nil) } return int(properties.ExitCode), nil @@ -223,7 +223,7 @@ func (process *Process) Stdio() (io.WriteCloser, io.ReadCloser, io.ReadCloser, e logrus.Debugf(title+" processid=%d", process.processID) if process.handle == 0 { - return nil, nil, nil, makeProcessError(process, operation, "", ErrAlreadyClosed) + return nil, nil, nil, makeProcessError(process, operation, ErrAlreadyClosed, nil) } var stdIn, stdOut, stdErr syscall.Handle @@ -234,9 +234,9 @@ func (process *Process) Stdio() (io.WriteCloser, io.ReadCloser, io.ReadCloser, e resultp *uint16 ) err := hcsGetProcessInfo(process.handle, &processInfo, &resultp) - err = processHcsResult(err, resultp) + events := processHcsResult(resultp) if err != nil { - return nil, nil, nil, makeProcessError(process, operation, "", err) + return nil, nil, nil, makeProcessError(process, operation, err, events) } stdIn, stdOut, stdErr = processInfo.StdInput, processInfo.StdOutput, processInfo.StdError @@ -250,7 +250,7 @@ func (process *Process) Stdio() (io.WriteCloser, io.ReadCloser, io.ReadCloser, e pipes, err := makeOpenFiles([]syscall.Handle{stdIn, stdOut, stdErr}) if err != nil { - return nil, nil, nil, makeProcessError(process, operation, "", err) + return nil, nil, nil, makeProcessError(process, operation, err, nil) } logrus.Debugf(title+" succeeded processid=%d", process.processID) @@ -267,7 +267,7 @@ func (process *Process) CloseStdin() error { logrus.Debugf(title+" processid=%d", process.processID) if process.handle == 0 { - return makeProcessError(process, operation, "", ErrAlreadyClosed) + return makeProcessError(process, operation, ErrAlreadyClosed, nil) } modifyRequest := processModifyRequest{ @@ -286,9 +286,9 @@ func (process *Process) CloseStdin() error { var resultp *uint16 err = hcsModifyProcess(process.handle, modifyRequestStr, &resultp) - err = processHcsResult(err, resultp) + events := processHcsResult(resultp) if err != nil { - return makeProcessError(process, operation, "", err) + return makeProcessError(process, operation, err, events) } logrus.Debugf(title+" succeeded processid=%d", process.processID) @@ -310,11 +310,11 @@ func (process *Process) Close() error { } if err := process.unregisterCallback(); err != nil { - return makeProcessError(process, operation, "", err) + return makeProcessError(process, operation, err, nil) } if err := hcsCloseProcess(process.handle); err != nil { - return makeProcessError(process, operation, "", err) + return makeProcessError(process, operation, err, nil) } process.handle = 0 diff --git a/internal/hcs/system.go b/internal/hcs/system.go index d060efabd0..6411cbc46e 100644 --- a/internal/hcs/system.go +++ b/internal/hcs/system.go @@ -85,19 +85,21 @@ func CreateComputeSystem(id string, hcsDocumentInterface interface{}, additional if createError == nil || IsPending(createError) { if err := computeSystem.registerCallback(); err != nil { - // Terminate the computeSystem if it still exists. We're okay to ignore a failure here. + // Terminate the compute system if it still exists. We're okay to + // ignore a failure here. computeSystem.Terminate() - return nil, makeSystemError(computeSystem, operation, "", err) + return nil, makeSystemError(computeSystem, operation, "", err, nil) } } - err = processAsyncHcsResult(createError, resultp, computeSystem.callbackNumber, hcsNotificationSystemCreateCompleted, &defaultTimeout) + events, err := processAsyncHcsResult(createError, resultp, computeSystem.callbackNumber, hcsNotificationSystemCreateCompleted, &defaultTimeout) if err != nil { if err == ErrTimeout { - // Terminate the compute system if it still exists. We're okay to ignore a failure here. + // Terminate the compute system if it still exists. We're okay to + // ignore a failure here. computeSystem.Terminate() } - return nil, makeSystemError(computeSystem, operation, hcsDocument, err) + return nil, makeSystemError(computeSystem, operation, hcsDocument, err, events) } logrus.Debugf(title+" succeeded id=%s handle=%d", id, computeSystem.handle) @@ -119,15 +121,15 @@ func OpenComputeSystem(id string) (*System, error) { resultp *uint16 ) err := hcsOpenComputeSystem(id, &handle, &resultp) - err = processHcsResult(err, resultp) + events := processHcsResult(resultp) if err != nil { - return nil, makeSystemError(computeSystem, operation, "", err) + return nil, makeSystemError(computeSystem, operation, "", err, events) } computeSystem.handle = handle if err := computeSystem.registerCallback(); err != nil { - return nil, makeSystemError(computeSystem, operation, "", err) + return nil, makeSystemError(computeSystem, operation, "", err, nil) } logrus.Debugf(title+" succeeded id=%s handle=%d", id, handle) @@ -152,9 +154,9 @@ func GetComputeSystems(q schema1.ComputeSystemQuery) ([]schema1.ContainerPropert computeSystemsp *uint16 ) err = hcsEnumerateComputeSystems(query, &computeSystemsp, &resultp) - err = processHcsResult(err, resultp) + events := processHcsResult(resultp) if err != nil { - return nil, err + return nil, &HcsError{Op: operation, Err: err, Events: events} } if computeSystemsp == nil { @@ -179,14 +181,14 @@ func (computeSystem *System) Start() error { logrus.Debugf(title+" id=%s", computeSystem.ID) if computeSystem.handle == 0 { - return makeSystemError(computeSystem, operation, "", ErrAlreadyClosed) + return makeSystemError(computeSystem, operation, "", ErrAlreadyClosed, nil) } var resultp *uint16 err := hcsStartComputeSystem(computeSystem.handle, "", &resultp) - err = processAsyncHcsResult(err, resultp, computeSystem.callbackNumber, hcsNotificationSystemStartCompleted, &defaultTimeout) + events, err := processAsyncHcsResult(err, resultp, computeSystem.callbackNumber, hcsNotificationSystemStartCompleted, &defaultTimeout) if err != nil { - return makeSystemError(computeSystem, operation, "", err) + return makeSystemError(computeSystem, operation, "", err, events) } logrus.Debugf(title+" succeeded id=%s", computeSystem.ID) @@ -203,14 +205,14 @@ func (computeSystem *System) Shutdown() error { logrus.Debugf(title+" id=%s", computeSystem.ID) if computeSystem.handle == 0 { - return makeSystemError(computeSystem, operation, "", ErrAlreadyClosed) + return makeSystemError(computeSystem, operation, "", ErrAlreadyClosed, nil) } var resultp *uint16 err := hcsShutdownComputeSystem(computeSystem.handle, "", &resultp) - err = processHcsResult(err, resultp) + events := processHcsResult(resultp) if err != nil { - return makeSystemError(computeSystem, operation, "", err) + return makeSystemError(computeSystem, operation, "", err, events) } logrus.Debugf(title+" succeeded id=%s", computeSystem.ID) @@ -227,14 +229,14 @@ func (computeSystem *System) Terminate() error { logrus.Debugf(title+" id=%s", computeSystem.ID) if computeSystem.handle == 0 { - return makeSystemError(computeSystem, operation, "", ErrAlreadyClosed) + return makeSystemError(computeSystem, operation, "", ErrAlreadyClosed, nil) } var resultp *uint16 err := hcsTerminateComputeSystem(computeSystem.handle, "", &resultp) - err = processHcsResult(err, resultp) + events := processHcsResult(resultp) if err != nil { - return makeSystemError(computeSystem, operation, "", err) + return makeSystemError(computeSystem, operation, "", err, events) } logrus.Debugf(title+" succeeded id=%s", computeSystem.ID) @@ -249,7 +251,7 @@ func (computeSystem *System) Wait() error { err := waitForNotification(computeSystem.callbackNumber, hcsNotificationSystemExited, nil) if err != nil { - return makeSystemError(computeSystem, operation, "", err) + return makeSystemError(computeSystem, operation, "", err, nil) } logrus.Debugf(title+" succeeded id=%s", computeSystem.ID) @@ -265,7 +267,7 @@ func (computeSystem *System) WaitTimeout(timeout time.Duration) error { err := waitForNotification(computeSystem.callbackNumber, hcsNotificationSystemExited, &timeout) if err != nil { - return makeSystemError(computeSystem, operation, "", err) + return makeSystemError(computeSystem, operation, "", err, nil) } logrus.Debugf(title+" succeeded id=%s", computeSystem.ID) @@ -280,9 +282,9 @@ func (computeSystem *System) Properties(query string) (*schema1.ContainerPropert propertiesp *uint16 ) err := hcsGetComputeSystemProperties(computeSystem.handle, query, &propertiesp, &resultp) - err = processHcsResult(err, resultp) + events := processHcsResult(resultp) if err != nil { - return nil, err + return nil, makeSystemError(computeSystem, "Properties", "", err, events) } if propertiesp == nil { @@ -305,14 +307,14 @@ func (computeSystem *System) Pause() error { logrus.Debugf(title+" id=%s", computeSystem.ID) if computeSystem.handle == 0 { - return makeSystemError(computeSystem, operation, "", ErrAlreadyClosed) + return makeSystemError(computeSystem, operation, "", ErrAlreadyClosed, nil) } var resultp *uint16 err := hcsPauseComputeSystem(computeSystem.handle, "", &resultp) - err = processAsyncHcsResult(err, resultp, computeSystem.callbackNumber, hcsNotificationSystemPauseCompleted, &defaultTimeout) + events, err := processAsyncHcsResult(err, resultp, computeSystem.callbackNumber, hcsNotificationSystemPauseCompleted, &defaultTimeout) if err != nil { - return makeSystemError(computeSystem, operation, "", err) + return makeSystemError(computeSystem, operation, "", err, events) } logrus.Debugf(title+" succeeded id=%s", computeSystem.ID) @@ -328,14 +330,14 @@ func (computeSystem *System) Resume() error { logrus.Debugf(title+" id=%s", computeSystem.ID) if computeSystem.handle == 0 { - return makeSystemError(computeSystem, operation, "", ErrAlreadyClosed) + return makeSystemError(computeSystem, operation, "", ErrAlreadyClosed, nil) } var resultp *uint16 err := hcsResumeComputeSystem(computeSystem.handle, "", &resultp) - err = processAsyncHcsResult(err, resultp, computeSystem.callbackNumber, hcsNotificationSystemResumeCompleted, &defaultTimeout) + events, err := processAsyncHcsResult(err, resultp, computeSystem.callbackNumber, hcsNotificationSystemResumeCompleted, &defaultTimeout) if err != nil { - return makeSystemError(computeSystem, operation, "", err) + return makeSystemError(computeSystem, operation, "", err, events) } logrus.Debugf(title+" succeeded id=%s", computeSystem.ID) @@ -355,7 +357,7 @@ func (computeSystem *System) CreateProcess(c *schema1.ProcessConfig) (*Process, ) if computeSystem.handle == 0 { - return nil, makeSystemError(computeSystem, operation, "", ErrAlreadyClosed) + return nil, makeSystemError(computeSystem, operation, "", ErrAlreadyClosed, nil) } // If we are not emulating a console, ignore any console size passed to us @@ -366,16 +368,16 @@ func (computeSystem *System) CreateProcess(c *schema1.ProcessConfig) (*Process, configurationb, err := json.Marshal(c) if err != nil { - return nil, makeSystemError(computeSystem, operation, "", err) + return nil, makeSystemError(computeSystem, operation, "", err, nil) } configuration := string(configurationb) logrus.Debugf(title+" id=%s config=%s", computeSystem.ID, configuration) err = hcsCreateProcess(computeSystem.handle, configuration, &processInfo, &processHandle, &resultp) - err = processHcsResult(err, resultp) + events := processHcsResult(resultp) if err != nil { - return nil, makeSystemError(computeSystem, operation, configuration, err) + return nil, makeSystemError(computeSystem, operation, configuration, err, events) } process := &Process{ @@ -390,7 +392,7 @@ func (computeSystem *System) CreateProcess(c *schema1.ProcessConfig) (*Process, } if err := process.registerCallback(); err != nil { - return nil, makeSystemError(computeSystem, operation, "", err) + return nil, makeSystemError(computeSystem, operation, "", err, nil) } logrus.Debugf(title+" succeeded id=%s processid=%d", computeSystem.ID, process.processID) @@ -410,13 +412,13 @@ func (computeSystem *System) OpenProcess(pid int) (*Process, error) { ) if computeSystem.handle == 0 { - return nil, makeSystemError(computeSystem, operation, "", ErrAlreadyClosed) + return nil, makeSystemError(computeSystem, operation, "", ErrAlreadyClosed, nil) } err := hcsOpenProcess(computeSystem.handle, uint32(pid), &processHandle, &resultp) - err = processHcsResult(err, resultp) + events := processHcsResult(resultp) if err != nil { - return nil, makeSystemError(computeSystem, operation, "", err) + return nil, makeSystemError(computeSystem, operation, "", err, events) } process := &Process{ @@ -426,7 +428,7 @@ func (computeSystem *System) OpenProcess(pid int) (*Process, error) { } if err := process.registerCallback(); err != nil { - return nil, makeSystemError(computeSystem, operation, "", err) + return nil, makeSystemError(computeSystem, operation, "", err, nil) } logrus.Debugf(title+" succeeded id=%s processid=%s", computeSystem.ID, process.processID) @@ -447,11 +449,11 @@ func (computeSystem *System) Close() error { } if err := computeSystem.unregisterCallback(); err != nil { - return makeSystemError(computeSystem, operation, "", err) + return makeSystemError(computeSystem, operation, "", err, nil) } if err := hcsCloseComputeSystem(computeSystem.handle); err != nil { - return makeSystemError(computeSystem, operation, "", err) + return makeSystemError(computeSystem, operation, "", err, nil) } computeSystem.handle = 0 @@ -525,7 +527,7 @@ func (computeSystem *System) Modify(config interface{}) error { title := "HCSShim::ComputeSystem::" + operation if computeSystem.handle == 0 { - return makeSystemError(computeSystem, operation, "", ErrAlreadyClosed) + return makeSystemError(computeSystem, operation, "", ErrAlreadyClosed, nil) } requestJSON, err := json.Marshal(config) @@ -538,9 +540,9 @@ func (computeSystem *System) Modify(config interface{}) error { var resultp *uint16 err = hcsModifyComputeSystem(computeSystem.handle, requestString, &resultp) - err = processHcsResult(err, resultp) + events := processHcsResult(resultp) if err != nil { - return makeSystemError(computeSystem, operation, "", err) + return makeSystemError(computeSystem, operation, "", err, events) } logrus.Debugf(title+" succeeded id=%s", computeSystem.ID) return nil diff --git a/internal/hcs/waithelper.go b/internal/hcs/waithelper.go index 1664707636..91e212c574 100644 --- a/internal/hcs/waithelper.go +++ b/internal/hcs/waithelper.go @@ -6,13 +6,13 @@ import ( "github.com/sirupsen/logrus" ) -func processAsyncHcsResult(err error, resultp *uint16, callbackNumber uintptr, expectedNotification hcsNotification, timeout *time.Duration) error { - err = processHcsResult(err, resultp) +func processAsyncHcsResult(err error, resultp *uint16, callbackNumber uintptr, expectedNotification hcsNotification, timeout *time.Duration) ([]ErrorEvent, error) { + events := processHcsResult(resultp) if IsPending(err) { - return waitForNotification(callbackNumber, expectedNotification, timeout) + return nil, waitForNotification(callbackNumber, expectedNotification, timeout) } - return err + return events, err } func waitForNotification(callbackNumber uintptr, expectedNotification hcsNotification, timeout *time.Duration) error {