2017-09-21 4 views
0

In Golang syscall.GetLastError() gibt den letzten Fehler nicht zurück. Siehe das folgende Beispielsyscall GetLastError() gibt keinen Fehler

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

err ist immer nil. Angenommen, machineNamePtr ist eine nicht existierende Maschine. Getestet den gleichen Code mit C++ und GetLastError() wirft RPC server is not available. Also warum nicht auf go?

EDIT

_OpenSCManager mit go generate erzeugt. //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

Es hängt von Ihrer Implementierung von _OpenSCManager ab. Gibt es nur einen 'Griff' zurück, wenn es erfolgreich ist? Dann wirst du hier nie einen Fehler bekommen. – RickyA

+0

übrigens. Wenn Sie etwas Privates für das Paket wünschen, starten Sie den Namen mit einem Kleinbuchstaben anstelle eines Unterstrichs. 'openSCManager' anstelle von' _OpenSCManager'. – RickyA

+0

Ja, es gibt nur einen 'Handle' zurück. Siehe [hier] (https://msdn.microsoft.com/de-de/library/windows/desktop/ms684323 (v = vs.85) .aspx). Ist das 'gehen' spezifisch, weil auf nativem C++ bekomme ich den letzten Fehler – maddin

Antwort

0

So endlich habe ich diese Arbeit bekam. Zuerst habe ich versucht, eine Fehlervariable mit folgender Signatur //sys _OpenSCManager(machineName *uint16, databaseName *uint16, desiredAcces ServiceAccessRight) (handle ServiceDatabaseHandle, lasterror error) = advapi32.OpenSCManagerW zurückzugeben. Aber go generate wirft immer Only last windows error is allowed as second return value.... Aber wenn Sie es in //sys ... (handle ServiceDatabaseHandle, err error) = advapi32.OpenSCManagerW ändern, wird der Code erfolgreich generiert. Du musst also explizit err error schreiben. Jemand weiß warum? Jetzt sieht die Funktion wie

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 
} 

aus und es gibt einen Fehler zurück. Sie müssen also nicht GetLastError() anrufen.

0

IIUC, die syscall.Syscall() unter Windows automatisch und atomar Anrufe GetLastError() nach den tatsächlichen syscall Oberflächen. Das sollte verständlich sein, wenn man bedenkt, dass, sobald eine Goroutine einen Syscall verlässt, der Go-Runtime-Scheduler es freigibt, es vorzusperren und eine weitere Goroutine auf dem Thread auszuführen, auf dem gerade die gerade vorweggenommene Goroutine gerade ausgeführt wurde.

Da GetLastError() Zugriffe pro-Thread-Zustand, wenn die zweiten goroutine andere syscall macht, wäre es wahrscheinlich, dass die letzten Fehlerwert dreschen, so im Rahmen von Go, jede syscall sollte getan mit dem folgenden Aufruf zu GetLastError() begleitet werden der Kontext eines einzelnen Syscall-Aufrufs - von der Go-Seite aus gesehen.

Verwandte Themen