...

Source file src/github.com/Microsoft/hcsshim/internal/guest/gcserr/errors.go

Documentation: github.com/Microsoft/hcsshim/internal/guest/gcserr

     1  package gcserr
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  
     7  	"github.com/pkg/errors"
     8  )
     9  
    10  // Hresult is a type corresponding to the HRESULT error type used on Windows.
    11  type Hresult int32
    12  
    13  // from
    14  // - https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/705fb797-2175-4a90-b5a3-3918024b10b8
    15  // - https://docs.microsoft.com/en-us/virtualization/api/hcs/reference/hcshresult
    16  const (
    17  	// HrNotImpl is the HRESULT for a not implemented function.
    18  	HrNotImpl = Hresult(-2147467263) // 0x80004001
    19  	// HrFail is the HRESULT for an invocation or unspecified failure.
    20  	HrFail = Hresult(-2147467259) // 0x80004005
    21  	// HrErrNotFound is the HRESULT for an invalid process id.
    22  	HrErrNotFound = Hresult(-2147023728) // 0x80070490
    23  	// HrErrInvalidArg is the HRESULT for One or more arguments are invalid.
    24  	HrErrInvalidArg = Hresult(-2147024809) // 0x80070057
    25  	// HvVmcomputeTimeout is the HRESULT for operations that timed out.
    26  	HvVmcomputeTimeout = Hresult(-1070137079) // 0xC0370109
    27  	// HrVmcomputeInvalidJSON is the HRESULT for failing to unmarshal a json
    28  	// string.
    29  	HrVmcomputeInvalidJSON = Hresult(-1070137075) // 0xC037010D
    30  	// HrVmcomputeSystemNotFound is the HRESULT for:
    31  	//
    32  	// A virtual machine or container with the specified identifier does not
    33  	// exist.
    34  	HrVmcomputeSystemNotFound = Hresult(-1070137074) // 0xC037010E
    35  	// HrVmcomputeSystemAlreadyExists is the HRESULT for:
    36  	//
    37  	// A virtual machine or container with the specified identifier already exists.
    38  	HrVmcomputeSystemAlreadyExists = Hresult(-1070137073) // 0xC037010F
    39  	// HrVmcomputeUnsupportedProtocolVersion is the HRESULT for an invalid
    40  	// protocol version range specified at negotiation.
    41  	HrVmcomputeUnsupportedProtocolVersion = Hresult(-1070137076) // 0xC037010C
    42  	// HrVmcomputeUnknownMessage is the HRESULT for unknown message types sent
    43  	// from the HCS.
    44  	HrVmcomputeUnknownMessage = Hresult(-1070137077) // 0xC037010B
    45  	// HrVmcomputeInvalidState is the HRESULT for:
    46  	//
    47  	// The requested virtual machine or container operation is not valid in the
    48  	// current state
    49  	HrVmcomputeInvalidState = Hresult(-2143878907) // 0x80370105
    50  	// HrVmcomputeSystemAlreadyStopped is the HRESULT for:
    51  	//
    52  	// The virtual machine or container with the specified identifier is not
    53  	// running
    54  	HrVmcomputeSystemAlreadyStopped = Hresult(-2143878896) // 0x80370110
    55  )
    56  
    57  // StackTracer is an interface originating (but not exported) from the
    58  // github.com/pkg/errors package. It defines something which can return a stack
    59  // trace.
    60  type StackTracer interface {
    61  	StackTrace() errors.StackTrace
    62  }
    63  
    64  // BaseStackTrace gets the earliest errors.StackTrace in the given error's cause
    65  // stack. This will be the stack trace which reaches closest to the error's
    66  // actual origin. It returns nil if no stack trace is found in the cause stack.
    67  func BaseStackTrace(e error) errors.StackTrace {
    68  	type causer interface {
    69  		Cause() error
    70  	}
    71  	cause := e
    72  	var tracer StackTracer
    73  	for cause != nil {
    74  		serr, ok := cause.(StackTracer)
    75  		if ok {
    76  			tracer = serr
    77  		}
    78  		cerr, ok := cause.(causer)
    79  		if !ok {
    80  			break
    81  		}
    82  		cause = cerr.Cause()
    83  	}
    84  	if tracer == nil {
    85  		return nil
    86  	}
    87  	return tracer.StackTrace()
    88  }
    89  
    90  type baseHresultError struct {
    91  	hresult Hresult
    92  }
    93  
    94  func (e *baseHresultError) Error() string {
    95  	return fmt.Sprintf("HRESULT: 0x%x", uint32(e.Hresult()))
    96  }
    97  func (e *baseHresultError) Hresult() Hresult {
    98  	return e.hresult
    99  }
   100  
   101  type wrappingHresultError struct {
   102  	cause   error
   103  	hresult Hresult
   104  }
   105  
   106  func (e *wrappingHresultError) Error() string {
   107  	return fmt.Sprintf("HRESULT 0x%x", uint32(e.Hresult())) + ": " + e.Cause().Error()
   108  }
   109  func (e *wrappingHresultError) Hresult() Hresult {
   110  	return e.hresult
   111  }
   112  func (e *wrappingHresultError) Cause() error {
   113  	return e.cause
   114  }
   115  func (e *wrappingHresultError) Format(s fmt.State, verb rune) {
   116  	switch verb {
   117  	case 'v':
   118  		if s.Flag('+') {
   119  			fmt.Fprintf(s, "%+v\n", e.Cause())
   120  			return
   121  		}
   122  		fallthrough
   123  	case 's':
   124  		_, _ = io.WriteString(s, e.Error())
   125  	case 'q':
   126  		fmt.Fprintf(s, "%q", e.Error())
   127  	}
   128  }
   129  func (e *wrappingHresultError) StackTrace() errors.StackTrace {
   130  	type stackTracer interface {
   131  		StackTrace() errors.StackTrace
   132  	}
   133  	serr, ok := e.Cause().(stackTracer)
   134  	if !ok {
   135  		return nil
   136  	}
   137  	return serr.StackTrace()
   138  }
   139  
   140  // NewHresultError produces a new error with the given HRESULT.
   141  func NewHresultError(hresult Hresult) error {
   142  	return &baseHresultError{hresult: hresult}
   143  }
   144  
   145  // WrapHresult produces a new error with the given HRESULT and wrapping the
   146  // given error.
   147  func WrapHresult(e error, hresult Hresult) error {
   148  	return &wrappingHresultError{
   149  		cause:   e,
   150  		hresult: hresult,
   151  	}
   152  }
   153  
   154  // GetHresult iterates through the error's cause stack (similar to how the
   155  // Cause function in github.com/pkg/errors operates). At the first error it
   156  // encounters which implements the Hresult() method, it return's that error's
   157  // HRESULT. This allows errors higher up in the cause stack to shadow the
   158  // HRESULTs of errors lower down.
   159  func GetHresult(e error) (Hresult, error) {
   160  	type hresulter interface {
   161  		Hresult() Hresult
   162  	}
   163  	type causer interface {
   164  		Cause() error
   165  	}
   166  	cause := e
   167  	for cause != nil {
   168  		herr, ok := cause.(hresulter)
   169  		if ok {
   170  			return herr.Hresult(), nil
   171  		}
   172  		cerr, ok := cause.(causer)
   173  		if !ok {
   174  			break
   175  		}
   176  		cause = cerr.Cause()
   177  	}
   178  	return -1, errors.Errorf("no HRESULT found in cause stack for error %s", e)
   179  }
   180  

View as plain text