== A caution about cgo's error returns for errno Go's [[cgo https://golang.org/cmd/cgo/]] system for calling C functions offers a very convenient feature. As the documentation puts it: > Any C function (even void functions) may be called in a multiple > assignment context to retrieve both the return value (if any) and the > C errno variable as an error [...] Reading this, you may be tempted to write more or less standard Go error-handling code like the following: .pn prewrap on > kcid, err := C.kstat_chain_update(t.kc) > if err != nil { > return err > } This code is a potential mistake. Unless the documentation for the C function you're calling says so explicitly, ~~there is no guarantee that _errno_ is zero on success~~. If the function returns success but _errno_ is non-zero, [[cgo]] will dutifully generate a non-nil error return from it and then your Go code will bail out with an error that isn't. This is not cgo's fault. Cgo has no magic knowledge of what C function return values are and aren't errors, so all it can do is exactly what it said it was going to do; if _errno_ is non zero, you get an error version of it. This is just a C API issue (that ultimately comes about because _errno_ is both an implicit return and global state). You'd never write code like this in Go, where 'only return non-nil error on actual errors' is well established, but we're stuck with the C API that we actually have instead of the Go-like one we'd like. So we have to deal with it, which means checking return values explicitly. (In this case the real 'there has been an error' marker is a _kcid_ return value of -1. I actually hit an irregular test failure when my code was just checking _err_, which is how I re-stubbed my toe on this particular C API issue.) PS: the ultimate cause of this is that C code often doesn't explicitly set _errno_ to zero on success but instead leaves it alone, which means _errno_ can wind up set from whatever internal system call or library routine last failed and set it. There are many possibilities for how this can happen; a classical one is seeing _ENOTTY_ from something checking to see if the file descriptor it is writing to is a TTY and so should be in line-buffered mode. (In my case I saw _EAGAIN_, which I believe was [[the OmniOS kernel ../solaris/KStatProgrammingNotes]] telling _``kstat_chain_update()''_ that the buffer it had been given wasn't large enough, please try again with a bigger one.)