Skip to content
Open
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
4 changes: 0 additions & 4 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,6 @@ linters:
- staticcheck
path: internal/winapi/
text: "ST1003:"
- linters:
- staticcheck
path: internal/vmcompute/
text: "ST1003:"
- linters:
- staticcheck
path: internal/regstate/
Expand Down
8 changes: 6 additions & 2 deletions internal/gcs/process.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,10 @@ func (p *Process) ExitCode() (_ int, err error) {
return -1, errors.New("process not exited")
}
if err := p.waitCall.Err(); err != nil {
return -1, err
var rerr *rpcError
if !errors.As(err, &rerr) || uint32(rerr.result) != hrNotFound {
return -1, err
}
}
return int(p.waitResp.ExitCode), nil
}
Expand Down Expand Up @@ -274,7 +277,8 @@ func (p *Process) Stdio() (stdin io.Writer, stdout, stderr io.Reader) {
// Wait waits for the process (or guest connection) to terminate.
func (p *Process) Wait() error {
p.waitCall.Wait()
return p.waitCall.Err()
_, err := p.ExitCode()
return err
}

func (p *Process) waitBackground() {
Expand Down
163 changes: 0 additions & 163 deletions internal/hcs/callback.go

This file was deleted.

63 changes: 48 additions & 15 deletions internal/hcs/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,15 +99,36 @@ type ErrorEvent struct {
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)
//Data []EventData `json:"Data,omitempty"` // Omit this as HCS doesn't encode this well. It's more confusing to include.
}

// hcsResult mirrors the HCS [ResultError] document and implements [error]
// so callers can recover it via [errors.As]. The unexported cause keeps
// [errors.Is] working against the underlying syscall errno.
//
// [ResultError]: https://learn.microsoft.com/en-us/virtualization/api/hcs/schemareference#ResultError
type hcsResult struct {
Error int32
ErrorMessage string
// ErrorCode mirrors the "Error" JSON field; renamed to avoid colliding
// with the [hcsResult.Error] method.
ErrorCode int32 `json:"Error,omitempty"`
ErrorMessage string `json:"ErrorMessage,omitempty"`
ErrorEvents []ErrorEvent `json:"ErrorEvents,omitempty"`

cause error
}

func (r *hcsResult) Error() string {
if r.cause != nil {
return r.cause.Error()
}
if r.ErrorMessage != "" {
return r.ErrorMessage
}
return fmt.Sprintf("hcs result: 0x%08x", uint32(r.ErrorCode))
}

func (r *hcsResult) Unwrap() error { return r.cause }

func (ev *ErrorEvent) String() string {
evs := "[Event Detail: " + ev.Message
if ev.StackTrace != "" {
Expand All @@ -129,14 +150,26 @@ func (ev *ErrorEvent) String() string {
return evs
}

func processHcsResult(ctx context.Context, resultJSON string) []ErrorEvent {
if resultJSON != "" {
result := &hcsResult{}
if err := json.Unmarshal([]byte(resultJSON), result); err != nil {
log.G(ctx).WithError(err).Warning("Could not unmarshal HCS result")
return nil
}
return result.ErrorEvents
// wrapHcsResult attaches the parsed HCS ResultError document to err so
// callers can recover it via `errors.As(err, new(*hcsResult))`. Returns
// err unchanged when the document is empty or unparseable.
func wrapHcsResult(ctx context.Context, err error, resultJSON string) error {
if err == nil || resultJSON == "" {
return err
}
r := &hcsResult{cause: err}
if jerr := json.Unmarshal([]byte(resultJSON), r); jerr != nil {
log.G(ctx).WithError(jerr).Warning("Could not unmarshal HCS result")
return err
}
return r
}

// eventsFromError returns the ErrorEvents from any wrapped HCS result in err.
func eventsFromError(err error) []ErrorEvent {
var r *hcsResult
if errors.As(err, &r) {
return r.ErrorEvents
}
return nil
}
Expand Down Expand Up @@ -201,7 +234,7 @@ func (e *SystemError) Error() string {
return s
}

func makeSystemError(system *System, op string, err error, events []ErrorEvent) error {
func makeSystemError(system *System, op string, err error) error {
// Don't double wrap errors
var e *SystemError
if errors.As(err, &e) {
Expand All @@ -213,7 +246,7 @@ func makeSystemError(system *System, op string, err error, events []ErrorEvent)
HcsError: HcsError{
Op: op,
Err: err,
Events: events,
Events: eventsFromError(err),
},
}
}
Expand All @@ -235,7 +268,7 @@ func (e *ProcessError) Error() string {
return s
}

func makeProcessError(process *Process, op string, err error, events []ErrorEvent) error {
func makeProcessError(process *Process, op string, err error) error {
// Don't double wrap errors
var e *ProcessError
if errors.As(err, &e) {
Expand All @@ -247,7 +280,7 @@ func makeProcessError(process *Process, op string, err error, events []ErrorEven
HcsError: HcsError{
Op: op,
Err: err,
Events: events,
Events: eventsFromError(err),
},
}
}
Expand Down
Loading
Loading