2017-09-21 6 views
0

ゴランでsyscall.GetLastError()は最後のエラーを返しません。syscall GetLastError()はエラーを返しません

if handle := _OpenSCManager(machineNamePtr, databaseNamePtr, desiredAccess); handle == nil { 
    if err := syscall.GetLastError(); err != nil { 
     return InvalidServiceDatabaseHandleHandle, ServiceErrno(err.(syscall.Errno)) 
    } 
} 

err次の例を参照してください常にnilです。 machineNamePtrはexsiting以外のマシンであるとします。同じコードをC++でテストし、GetLastError()RPC server is not availableにスローされました。だからgoにいないのはなぜですか?

EDIT

_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 

}

+0

これは、 '_OpenSCManager'の実装によって異なります。それは成功した場合にのみ 'handle'を返しますか?それでは、ここではエラーは発生しません。 – RickyA

+0

btw。パッケージにプライベートなものが必要なときは、アンダースコアの代わりに小文字を使用して名前を開始します。 '_OpenSCManager'ではなく' openSCManager'を使用してください。 – RickyA

+0

はい、 'handle'だけを返します。 [ここ](https://msdn.microsoft.com/de-de/library/windows/desktop/ms684323(v = vs.85).aspx)を参照してください。ネイティブのC++で最後のエラーが発生するので、これは 'go'に特化されています – maddin

答えて

0

だから、最終的に私はこの作業を持っています。まず、次のシグネチャ//sys _OpenSCManager(machineName *uint16, databaseName *uint16, desiredAcces ServiceAccessRight) (handle ServiceDatabaseHandle, lasterror error) = advapi32.OpenSCManagerWでエラー変数を返そうとしました。しかし、go generateは常にOnly last windows error is allowed as second return value...をスローします。しかし、//sys ... (handle ServiceDatabaseHandle, err error) = advapi32.OpenSCManagerWに変更すると、コードが正常に生成されます。明示的にはerr errorと書かなければなりません。なぜ誰かが知っていますか?関数は次のようになります

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 
} 

これはエラーを返します。したがって、GetLastError()に電話する必要はありません。

0

IIUC、実際のシステムコールの終了後にWindows上syscall.Syscall()自動的と不可分通話GetLastError()。 goroutineがシステムコールを終了するとすぐGo実行時スケジューラはそれをプリエンプトして、スレッド上で別のゴルーチンを実行することができます。just-preempted goroutineが実行されていました。

GetLastError()第二ゴルーチンは別のシステムコールを行った場合ゴーの文脈で、各システムコールがで行わGetLastError()に次の呼び出しを伴うべきであるので、それはおそらく、その最後のエラー値をスラッシュう、スレッドごとの状態へのアクセスとなるため単一のシステムコールのコンテキスト - Go側から見たもの。

関連する問題