do you need to clear WSAGetLastError() and if so how? - winapi

In Unix, some function calls don't promise to clear errno so you can't detect an error by checking errno unless you clear it yourself before calling. E.g.:
errno = 0;
some_function();
if ( errno ) {
:
:
On Windows WSAGetLastError() is used in lieu of errno. Do all WSA functions clear the last error upon success? Or if not, is there a way to clear it manually? If not that either, what do you do?

No you don't need to clear it. You only call WSAGetLastError if the function failed.
The normal pattern is just:
if (0 != WSAEventSelect(...))
{
int error = WSAGetLastError();
handle_error(error);
}
else
{
WaitForSingleObject(...);
...
}
There is a WSASetLastError function you could call but you normally have no reason to.
Most functions on Windows are implemented so that they only set the error code on failure.
int WSAWhatever()
{
BOOL success = something() && somethingelse();
if (!success)
{
WSASetLastError(WSASOMETHING);
return SOCKET_ERROR;
}
return 0;
}
There are a couple of places in Win32 where you need to clear the error with SetLastError (GetFileSize etc.) but it is called out in the documentation on MSDN if required.

It depends on the function. If you find a function whose documentation tells you to call WSASetLastError(0) before calling the function, then do so.
However, that would be pretty rare. As with the Win32 error code (managed by GetLastError and SetLastError), the usual pattern is that you should only call WSAGetLastError if the function indicates that it failed. Typically failure is indicated by the return value of the function, but this varies from function to function, and the documentation should be called. The usual pattern is like so:
if (!some_function())
{
int err = WSAGetLastError();
// do something with err
}
Generally the function will only promise to call WSASetLastError() in case of failure. So the class mistake that people make is to use WSAGetLastError() to check for errors. That code would be like this:
// don't use this code, it is an anti-pattern
some_function();
int err = WSAGetLastError();
if (err != 0)
// do something with err
}
You must always carefully read the documentation for each function that you call because there are quite a few different patterns in use.

Related

Go errors: Is() and As() claim to be recursive, is there any type that implements the error interface and supports this recursion - bug free?

Everywhere I look, the "way" to "wrap" errors in Go is to use fmt.Errof with the %w verb
https://go.dev/blog/go1.13-errors
However, fmt.Errorf does not recursively wrap errors. There is no way to use it to wrap three previously defined errors (Err1, Err2, and Err3) and then check the result by using Is() and get true for each those three errors.
FINAL EDIT:
Thanks to #mkopriva's answer and comments below it, I now have a straightforward way to implement this (although, I am still curious if there is some standard type which does this). In the absence of an example, my attempts at creating one failed. The piece I was missing was adding an Is and As method to my type. Because the custom type needs to contain an error and a pointer to the next error, the custom Is and As methods allows us to compare the error contained in the custom type, rather than the custom type itself.
Here is a working example: https://go.dev/play/p/6BYGgIb728k
Highlights from the above link
type errorChain struct {
err error
next *errorChain
}
//These two functions were the missing ingredient
//Defined this way allows for full functionality even if
//The wrapped errors are also chains or other custom types
func (c errorChain) Is(err error) bool { return errors.Is(c.err, err) }
func (c errorChain) As(target any) bool { return errors.As(c.err, target) }
//Omitting Error and Unwrap methods for brevity
func Wrap(errs ...error) error {
out := errorChain{err: errs[0]}
n := &out
for _, err := range errs[1:] {
n.next = &errorChain{err: err}
n = n.next
}
return out
}
var Err0 = errors.New("error 0")
var Err1 = errors.New("error 1")
var Err2 = errors.New("error 2")
var Err3 = errors.New("error 3")
func main() {
//Check basic Is functionality
errs := Wrap(Err1, Err2, Err3)
fmt.Println(errs) //error 1: error 2: error 3
fmt.Println(errors.Is(errs, Err0)) //false
fmt.Println(errors.Is(errs, Err2)) //true
}
While the Go source specifically mentions the ability to define an Is method, the example does not implement it in a way that can solve my issue and the discussion do not make it immediately clear that it would be needed to utilize the recursive nature of errors.Is.
AND NOW BACK TO THE ORIGINAL POST:
Is there something built into Go where this does work?
I played around with making one of my own (several attempts), but ran into undesirable issues. These issues stem from the fact that errors in Go appear to be compared by address. i.e. if Err1 and Err2 point to the same thing, they are the same.
This causes me issues. I can naively get errors.Is and errors.As to work recursively with a custom error type. It is straightforward.
Make a type that implements the error interface (has an Error() string method)
The type must have a member that represents the wrapped error which is a pointer to its own type.
Implement an Unwrap() error method that returns the wrapped error.
Implement some method which wraps one error with another
It seems good. But there is trouble.
Since errors are pointers, if I make something like myWrappedError = Wrap(Err1, Err2) (in this case assume Err1 is being wrapped by Err2). Not only will errors.Is(myWrappedError, Err1) and errors.Is(myWrappedError, Err2) return true, but so will errors.Is(Err2, Err1)
Should the need arise to make myOtherWrappedError = Wrap(Err3, Err2) and later call errors.Is(myWrappedError, Err1) it will now return false! Making myOtherWrappedError changes myWrappedError.
I tried several approaches, but always ran into related issues.
Is this possible? Is there a Go library which does this?
NOTE: I am more interested in the presumably already existing right way to do this rather than the specific thing that is wrong with my basic attempt
Edit 3: As suggested by one of the answers, the issue in my first code is obviously that I modify global errors. I am aware, but failed to adequately communicate. Below, I will include other broken code which uses no pointers and modifies no globals.
Edit 4: slight modification to make it work more, but it is still broken
See https://go.dev/play/p/bSytCysbujX
type errorGroup struct {
err error
wrappedErr error
}
//...implemention Unwrap and Error excluded for brevity
func Wrap(inside error, outside error) error {
return &errorGroup{outside, inside}
}
var Err1 = errorGroup{errors.New("error 1"), nil}
var Err2 = errorGroup{errors.New("error 2"), nil}
var Err3 = errorGroup{errors.New("error 3"), nil}
func main() {
errs := Wrap(Err1, Err2)
errs = Wrap(errs, Err3)
fmt.Println(errs)//error 3: error 2: error 1
fmt.Println(errors.Is(errs, Err1)) //true
fmt.Println(errors.Is(errs, Err2)) //false <--- a bigger problem
fmt.Println(errors.Is(errs, Err3)) //false <--- a bigger problem
}
Edit 2: playground version shortened
See https://go.dev/play/p/swFPajbMcXA for an example of this.
EDIT 1: A trimmed version of my code focusing on the important parts:
type errorGroup struct {
err error
wrappedErr *errorGroup
}
//...implemention Unwrap and Error excluded for brevity
func Wrap(errs ...*errorGroup) (r *errorGroup) {
r = &errorGroup{}
for _, err := range errs {
err.wrappedErr = r
r = err
}
return
}
var Err0 = &errorGroup{errors.New("error 0"), nil}
var Err1 = &errorGroup{errors.New("error 1"), nil}
var Err2 = &errorGroup{errors.New("error 2"), nil}
var Err3 = &errorGroup{errors.New("error 3"), nil}
func main() {
errs := Wrap(Err1, Err2, Err3)//error 3: error 2: error 1
fmt.Println(errors.Is(errs, Err1)) //true
//Creating another wrapped error using the Err1, Err2, or Err3 breaks the previous wrap, errs.
_ = Wrap(Err0, Err2, Err3)
fmt.Println(errors.Is(errs, Err1)) //false <--- the problem
}
You can use something like this:
type errorChain struct {
err error
next *errorChain
}
func Wrap(errs ...error) error {
out := errorChain{err: errs[0]}
n := &out
for _, err := range errs[1:] {
n.next = &errorChain{err: err}
n = n.next
}
return out
}
func (c errorChain) Is(err error) bool {
return c.err == err
}
func (c errorChain) Unwrap() error {
if c.next != nil {
return c.next
}
return nil
}
https://go.dev/play/p/6oUGefSxhvF
Your code modifies package-global error values, so it is inherently broken. This defect has nothing to do with Go's error handling mechanics.
Per the documentation you linked, there are two error-handling helpers: Is, and As. Is lets you recursively unwrap an error, looking for a specific error value, which is necessarily a package global for this to be useful. As, on the other hand, lets you recursively unwrap an error looking for any wrapped error value of a given type.
How does wrapping work? You wrap error A in a new error value B. A Wrap() helper would necessarily return a new value, as fmt.Errorf does in the examples in the linked documentation. A Wrap helper should never modify the value of the error being wrapped. That value should be considered immutable. In fact, in any normal implementation, the value would be of type error, so that you can wrap any error, rather than just wrapping concentric values of your custom error type in each other; and, in that case, you have no access to the fields of the wrapped error to modify them anyway. Essentially, Wrap should be roughly:
func Wrap(err error) error {
return &errGroup{err}
}
And that's it. That's not very useful, because your implementation of errGroup doesn't really do anything - it provides no details about the error that occurred, it's just a container for other errors. For it to have value, it should have a string error message, or methods like some other error types' IsNotFound, or something that makes it more useful than just using error and fmt.Errorf.
Based on the usage in your example code, it also looks like you're presuming the use case is to say "I want to wrap A in B in C", which I've never seen in the wild and I cannot think of any scenario where that would be needed. The purpose of wrapping is to say "I've recieved error A, I'm going to wrap it in error B to add context, and return it". The caller might wrap that error in error C, and so on, which is what makes recursive wrapping valuable.
For example: https://go.dev/play/p/XeoONx19dgX
Instead of chaining/wrapping, you will "soon" (Go 1.20, as seen in Go 1.20-rc1 in Dec. 2022) be able to return a slice/tree of errors.
(In the meantime, mdobak/go-xerrors is a good alternative)
The release note explains:
Wrapping multiple errors
Go 1.20 expands support for error wrapping to permit an error to wrap
multiple other errors.
An error e can wrap more than one error by providing an Unwrap method
that returns a []error.
The errors.Is and errors.As functions have been updated to inspect
multiply wrapped errors.
The fmt.Errorf function now supports multiple occurrences of the %w
format verb, which will cause it to return an error that wraps all of
those error operands.
The new function errors.Join returns an error wrapping a list of
errors.
That comes from:
proposal: errors: add support for wrapping multiple errors
Background
Since Go 1.13, an error may wrap another by providing an Unwrap method returning the wrapped error.
The errors.Is and errors.As functions operate on chains of wrapped errors.
A common request is for a way to combine a list of errors into a single error.
Proposal
An error wraps multiple errors if its type has the method
Unwrap() []error
Reusing the name Unwrap avoids ambiguity with the existing singular Unwrap method.
Returning a 0-length list from Unwrap means the error doesn't wrap anything.
Callers must not modify the list returned by Unwrap.
The list returned by Unwrap must not contain any nil errors.
We replace the term "error chain" with "error tree".
The errors.Is and errors.As functions are updated to unwrap multiple errors.
Is reports a match if any error in the tree matches.
As finds the first matching error in a inorder preorder traversal of the tree.
The errors.Join function provides a simple implementation of a multierr.
It does not flatten errors.
// Join returns an error that wraps the given errors.
// Any nil error values are discarded.
// The error formats as the text of the given errors, separated by newlines.
// Join returns nil if errs contains no non-nil values.
func Join(errs ...error) error
The fmt.Errorf function permits multiple instances of the %w formatting verb.
The errors.Unwrap function is unaffected: It returns nil when called on an error with an Unwrap() []error method.
Why should this be in the standard library?
This proposal adds something which cannot be provided outside the standard library: Direct support for error trees in errors.Is and errors.As.
Existing combining errors operate by providing Is and As methods which inspect the contained errors, requiring each implementation to duplicate this logic, possibly in incompatible ways.
This is best handled in errors.Is and errors.As, for the same reason those functions handle singular unwrapping.
In addition, this proposal provides a common method for the ecosystem to use to represent combined errors, permitting interoperation between third-party implementations.
So far (Sept. 2022) this proposal seems a likely accept has been accepted!
CL 432575 starts the implementation.
There arr several approaches but there is one thing that you should keep in mind: if you have multiple errors, you may need to handle it as a slice of errors
For instance, imagine you need to check if all errors are the same, or there is at least one error of certain type you can use the snippet below.
You can extend this concept or use some existing library to handle multierrors
type Errors []error
func (errs Errors) String() string {
…
}
func (errs Errors) Any(target error) bool{
for _, err := range errs {
if errors.Is(err,target) {
return true
}
}
return false
}
func (errs Errors) All(target error) bool{
if len(errs) == 0 { return false }
for _, err := range errs {
if !errors.Is(err,target) {
return false
}
}
return true
}

Are there recoverable read errors for a net.Conn?

If the .Read() method of a net.Conn returns an error, does this imply that future reads also will fail with an error? Or are there recoverable errors? If so, how do I know whether/when to retry reads?
In general, you're not going to have any errors from a conn.Read operation that can be retried. Most uses of the io.Reader interface will assume that all errors are final.
Any net package errors that are assured to be retry-able will conform to the net.Error interface, and expose a Temporary method.
This is most often used in an Accept loop, like this paraphrased example from the http package
for {
rw, e := l.Accept()
if e != nil {
if ne, ok := e.(net.Error); ok && ne.Temporary() {
if tempDelay == 0 {
tempDelay = 5 * time.Millisecond
} else {
tempDelay *= 2
}
if max := 1 * time.Second; tempDelay > max {
tempDelay = max
}
time.Sleep(tempDelay)
continue
}
return e
}
}
Any other possible cases need to be handled on an individual basis, with knowledge of the protocol and situation at hand.
Timeout is the only recoverable error on read from a net.TCPConn and that error will only be returned when a read deadline is set on the connection.
Use Error.Temporary() to check for errors that may resolve on retry and Error.Timeout() to check for timeouts:
n, err := c.Read(buf)
// process buf[:n] bytes
if e.(net.Error); ok && e.Timeout() && e.Temporary() {
// handle recoverable read deadline expiration
} else if err != nil {
// handle other errors
}
See the specific error type of the net package https://golang.org/pkg/net/#OpError
It provides a specific Temporary() method to figure out if it is a non-terminal error.
To manually figure out which error is Temporary you have to go through each defined error within the net, os and some other internal packages.
To programmatically check for a temporary error, you might declare your own local temporary interface{ Temporary() bool }, or you can rely on this interface provided by the net package https://golang.org/pkg/net/#Error
The OpError.Temporary method test if its internal error implements the net.temporary interface (https://golang.org/src/net/net.go?s=16056:16090#L501), and if so returns the result of the call to Temporary() of the internal error, for example https://golang.org/src/net/net.go?s=19122:19157#L605.
I am unsure which read retry you are thinking about, however, internal fd.read methods implements retries for eagain
https://golang.org/src/internal/poll/fd_unix.go#L165

Empty return in func with return value in golang [duplicate]

This question already has answers here:
How does defer and named return value work?
(3 answers)
Closed 5 years ago.
I was reading some code written in Golang on Github and found a very interesting piece of code. I simplified it to be clear.
func Insert(docs ...interface{}) (err error) {
for i := 0; i < 3; i++ {
err = fmt.Errorf("")
if err.Error()!="EOF" {
return
}
}
return
}
I'm very confused about empty return here... How it works? Does he return nil as error or breaks for loop? I understand that this question looks dummy, but I cannot find any info on this in go docs... Also, I don't understand how we can return err, which is, as I understood, declared somehow in return. Does (err error) means that we already have an error variable available in our func which is used as default return value if none specified? Why then we implicitly make return err at the end of func?
I'll be very gratefull for explanation.
The function uses a "named" return value.
From the spec on return statements:
The expression list may be empty if the function's result type
specifies names for its result parameters. The result parameters act
as ordinary local variables and the function may assign values to them
as necessary. The "return" statement returns the values of these
variables.
Regardless of how they are declared, all the result values are
initialized to the zero values for their type upon entry to the
function. A "return" statement that specifies results sets the result
parameters before any deferred functions are executed.
Using named returns allows you to save some code on manually allocating local variables, and can sometimes clean up messy if/else statements or long lists of return values.
func a()(x []string, err error){
return
}
is really just shorthand for
func a() ([]string,error){
var x []string
var err error
return x,err
}
Its a bit shorter, and I agree that it may be less obvious.
Named returns are sometimes needed, as it allows things like accessing them inside a deferred function, but the naked return is just syntactic sugar as far as I can tell, and is never strictly required.
One place I see it commonly is in error return cases in functions that have many return values.
if(err != nil){
return
}
return a,b,c,nil
is easier than
if(err != nil){
return nil,nil,nil,err
}
return a,b,c,nil
when you have to write it a bunch of times. And you don't have to modify those returns if you change the signature to have additional "real" return values.
Most places I am using them in the codebase I just searched, they definitely seem to be hiding other smells, like overly complex multi-purpose functions, too deep if/else nesting and stuff like that.
Go's return values may be named. If so, they are treated as variables defined at the top of the function.
package main
import "fmt"
func split(sum int) (x, y int) {
x = sum * 4 / 9
y = sum - x
return
}
func main() {
fmt.Println(split(17))
}
https://tour.golang.org/basics/7
When you have a named return value (err here):
func Insert(docs ...interface{}) (err error) {
This creates a function-local variable by that name, and if you just call return with no parameters, it returns the local variable. So in this function,
return
Is the same as, and implies,
return err
This is detailed in the tour and in the spec.

how to ignore returned error in GO

I have started learning Go today.
One thing that makes me crazy, it's the err returned parameter.
Let's assume I need to nest few functions. like this:
return string(json.Marshal(MyData))
or more complex example:
return func1(func2(func3(MyData)))
Is it really necessary to write:
tmp1 , _ = func3(MyData)
tmp2 , _ = func2(tmp1)
tmp3 , _ = func1(tmp2)
return tmp3
That's annoying!
Is there any way to make the code looks cleaner?
It is possible to define a function to ignore errors, but Go's lack of generics make it so you'd have to use interface{} and typecasts all over the place, losing a lot of static guarantees from the typechecker in the process. It is extremely ugly. Don't do this.
func ignoreError(val interface {}, err error) interface {} {
return val
}
At every call to ignoreError() you would have to make a type cast to the expected return type.
Playground example
One possible abstraction pattern you will often see is to use a generic error handler.
This doesn't prevent you from having to deal with error values, but it does abstract the handling of errors away from the rest of your code.
Note that abstractions like these are considered "non-idiomatic" Go, the "pure" way is to explicitly handle errors in-place. This panic-driven alternative can still be very useful though, especially for quickly prototyping a script where you just want to dump all the errors in a console or logfile.
For reusable packages, I would stick to the verbose explicit way though, because others will expect error-producing functions to actually return error values, rather than using a panic-recover mechanism.
package main
import (
utils
)
func main() {
defer func() {
utils.Handle(func(err error) {
// Handle errors in a generic way,
// for example using println, or writing to http
})
}()
var result, err := someFragileFunction()
Check(err)
}
package utils
func Check(err error) {
if err != nil {
panic(err)
}
}
func Handle(handler func(err error)) {
if r := recover(); r != nil {
if err, ok := r.(error); ok {
handler(err)
} else {
panic(r)
}
}
}
The real answer is: Don't.
Never just ignore the errors.
Seriously. The errors are there for a reason. If a function returns an error,
it almost always means that it's possible, during the operation of your program,
even if it's 100% bug-free, for the function to fail. And if it does,
you don't usually want to just keep going as if nothing happened.
If you're absolutely sure that you're using a function in a way that ensures that it will never return a non-nil error (unless there's a bug in your program, and there always is), you might want to write a Must-style function like in the template package which panics with the returned error value.
Error handling is not noise. It's not clutter. It's not something you want
to get rid of. If it looks like 50% of your program is error
handling, that's because 50% of your program is, and should be, error handling.

What is the best way to group errors in go?

I was looking at net/http and crypto/x509
I wondering which approach is better and why.
net/http/http.go uses strings:
// HTTP request parsing errors.
type ProtocolError struct {
ErrorString string
}
func (err *ProtocolError) Error() string { return err.ErrorString }
var (
ErrHeaderTooLong = &ProtocolError{"header too long"}
ErrShortBody = &ProtocolError{"entity body too short"}
ErrNotSupported = &ProtocolError{"feature not supported"}
ErrUnexpectedTrailer = &ProtocolError{"trailer header without chunked transfer encoding"}
ErrMissingContentLength = &ProtocolError{"missing ContentLength in HEAD response"}
ErrNotMultipart = &ProtocolError{"request Content-Type isn't multipart/form-data"}
ErrMissingBoundary = &ProtocolError{"no multipart boundary param in Content-Type"}
)
crypto/x509/verify.go uses ints:
type InvalidReason int
const (
TooManyIntermediates
IncompatibleUsage
)
type CertificateInvalidError struct {
Cert *Certificate
Reason InvalidReason
}
func (e CertificateInvalidError) Error() string {
switch e.Reason {
case TooManyIntermediates:
return "x509: too many intermediates for path length constraint"
case IncompatibleUsage:
return "x509: certificate specifies an incompatible key usage"
}
return "x509: unknown error"
}
Both usage are good, but it depends on your needs.
If you find it useful to attach additional data to the error that doesn't show in the error message, then the approach in crypto/x509 is preferable.
But I think in most cases, the simple error string as found in the errors package is sufficient.
Edit
An error can have different "attributes":
Describing
The Error() method should return a short describing error message
Identifiable
By letting a package export the different errors it might return, you can identify them. This is either done like in the io package by exporting initialized error variables of same type:
if err == io.EOF { ... } // That's easy
Or like in the encoding/json package by exporting the different error types:
if mErr, ok := err.(*json.MarshalerError); ok { ... } // That's fairly easy
Or by doing like they do in the crypto/x509 package, by exporting the different Reasons (error codes):
if e, ok := err.(x509.CertificateInvalidError); ok && e.Reason == x509.Expired { ... } // Well, it works
Unique error code
If errors should have specific codes due to a protocol spec, these could be embedded in the error variable. The crypto/x509 package might be used for that, even though it is probably not the case.
But when it comes to how to solve it, I think there is no best approach, nor any clearly idiomatic one. The examples above shows you ways to do it and ways it is done in the standard libraries. Take your pick.
.. but maybe not using switch statements.

Resources