[英]syscall GetLastError() doesn't return error
In golang syscall.GetLastError()
doesn't return the last error. 在golang中, syscall.GetLastError()
不返回上一个错误。 See the following example 请参阅以下示例
if handle := _OpenSCManager(machineNamePtr, databaseNamePtr, desiredAccess); handle == nil {
if err := syscall.GetLastError(); err != nil {
return InvalidServiceDatabaseHandleHandle, ServiceErrno(err.(syscall.Errno))
}
}
err
is always nil
. err
永远是nil
。 Assume machineNamePtr
is a non exsiting machine. 假设machineNamePtr
是不存在的计算机。 Tested the same code with c++ and GetLastError()
throws RPC server is not available
. 使用c ++测试了相同的代码,并且GetLastError()
引发RPC server is not available
。 So why not on go
? 那么,为什么不go
呢?
EDIT 编辑
_OpenSCManager is generated with go generate
. _OpenSCManager是通过go generate
。 //sys _OpenSCManager(machineName *uint16, databaseName *uint16, desiredAcces ServiceAccessRight) (handle ServiceDatabaseHandle) = advapi32.OpenSCManagerW
func _OpenSCManager(machineName *uint16, databaseName *uint16, desiredAcces ServiceAccessRight) (handle ServiceDatabaseHandle) {
r0, _, _ := syscall.Syscall(procOpenSCManagerW.Addr(), 3, uintptr(unsafe.Pointer(machineName)), uintptr(unsafe.Pointer(databaseName)), uintptr(desiredAcces))
handle = ServiceDatabaseHandle(r0)
return
} }
So finally i've got this working. 所以终于我有了这个工作。 First i have tried to return an error variable with the following signature //sys _OpenSCManager(machineName *uint16, databaseName *uint16, desiredAcces ServiceAccessRight) (handle ServiceDatabaseHandle, lasterror error) = advapi32.OpenSCManagerW
. 首先,我尝试返回具有以下签名的错误变量//sys _OpenSCManager(machineName *uint16, databaseName *uint16, desiredAcces ServiceAccessRight) (handle ServiceDatabaseHandle, lasterror error) = advapi32.OpenSCManagerW
。 But go generate
throws always Only last windows error is allowed as second return value...
. 但是总是go generate
抛出异常。 Only last windows error is allowed as second return value...
But if you change it to //sys ... (handle ServiceDatabaseHandle, err error) = advapi32.OpenSCManagerW
it successfully generates the code. 但是,如果将其更改为//sys ... (handle ServiceDatabaseHandle, err error) = advapi32.OpenSCManagerW
它将成功生成代码。 So you explicit have to write err error
. 因此,您必须显式地编写err error
。 Someone knows why? 有人知道为什么吗? So now the function looks like 所以现在函数看起来像
func _OpenSCManager(machineName *uint16, databaseName *uint16, desiredAcces ServiceAccessRight) (handle ServiceDatabaseHandle, err error) {
r0, _, e1 := syscall.Syscall(procOpenSCManagerW.Addr(), 3, uintptr(unsafe.Pointer(machineName)), uintptr(unsafe.Pointer(databaseName)), uintptr(desiredAcces))
handle = ServiceDatabaseHandle(r0)
if handle == 0 {
if e1 != 0 {
err = errnoErr(e1)
} else {
err = syscall.EINVAL
}
}
return
}
and it returns an error. 它返回一个错误。 So there is no need to call GetLastError()
. 因此,无需调用GetLastError()
。
IIUC, the syscall.Syscall()
on Windows automatically and atomically calls GetLastError()
after the actual syscall finishes. IIUC,Windows上的syscall.Syscall()
在实际的系统调用完成后自动自动调用GetLastError()
。 That should be understandable once you consider that as soon as a goroutine exits from a syscall, the Go runtime scheduler is free to preempt it and run another goroutine on the very thread the just-preempted goroutine had just been running on. 一旦您考虑到goroutine从系统调用中退出,Go运行时调度程序就可以随意抢占它并在刚被抢占的goroutine运行于其上的线程上运行另一个goroutine,这应该是可以理解的。
Since GetLastError()
accesses per-thread state, if the second goroutine makes another syscall, it would likely thrash that last error value, so in the context of Go, each syscall should be accompanied with the following call to GetLastError()
done in the context of a single syscall invocation — as seen from the Go side. 由于GetLastError()
访问每个线程状态,因此,如果第二个goroutine进行了另一个系统调用,则可能会破坏该最后一个错误值,因此在Go的上下文中,每个系统调用都应伴随以下对GetLastError()
调用:单个syscall调用的上下文-从Go端看。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.