Create wrapper functions for each qemu C API that accepts a virErrorPtr parameter. This avoids accessing a thread local from a goroutine which may race with other goroutines doing native API calls in the same OS thread. Signed-off-by: Daniel P. Berrangé <berrange@xxxxxxxxxx> --- qemu.go | 31 ++++++++++--------- qemu_wrapper.go | 79 ++++++++++++++++++++++++++++++++++++++++++++----- qemu_wrapper.h | 33 +++++++++++++++++---- 3 files changed, 115 insertions(+), 28 deletions(-) diff --git a/qemu.go b/qemu.go index 3631b00..dd4f258 100644 --- a/qemu.go +++ b/qemu.go @@ -81,10 +81,11 @@ func (d *Domain) QemuMonitorCommand(command string, flags DomainQemuMonitorComma var cResult *C.char cCommand := C.CString(command) defer C.free(unsafe.Pointer(cCommand)) - result := C.virDomainQemuMonitorCommand(d.ptr, cCommand, &cResult, C.uint(flags)) + var err C.virError + result := C.virDomainQemuMonitorCommandWrapper(d.ptr, cCommand, &cResult, C.uint(flags), &err) if result != 0 { - return "", GetLastError() + return "", makeError(&err) } rstring := C.GoString(cResult) @@ -95,10 +96,11 @@ func (d *Domain) QemuMonitorCommand(command string, flags DomainQemuMonitorComma func (d *Domain) QemuAgentCommand(command string, timeout DomainQemuAgentCommandTimeout, flags uint32) (string, error) { cCommand := C.CString(command) defer C.free(unsafe.Pointer(cCommand)) - result := C.virDomainQemuAgentCommand(d.ptr, cCommand, C.int(timeout), C.uint(flags)) + var err C.virError + result := C.virDomainQemuAgentCommandWrapper(d.ptr, cCommand, C.int(timeout), C.uint(flags), &err) if result == nil { - return "", GetLastError() + return "", makeError(&err) } rstring := C.GoString(result) @@ -107,10 +109,10 @@ func (d *Domain) QemuAgentCommand(command string, timeout DomainQemuAgentCommand } func (c *Connect) DomainQemuAttach(pid uint32, flags uint32) (*Domain, error) { - - ptr := C.virDomainQemuAttach(c.ptr, C.uint(pid), C.uint(flags)) + var err C.virError + ptr := C.virDomainQemuAttachWrapper(c.ptr, C.uint(pid), C.uint(flags), &err) if ptr == nil { - return nil, GetLastError() + return nil, makeError(&err) } return &Domain{ptr: ptr}, nil } @@ -156,19 +158,18 @@ func (c *Connect) DomainQemuMonitorEventRegister(dom *Domain, event string, call defer C.free(unsafe.Pointer(cEvent)) goCallBackId := registerCallbackId(callback) - callbackPtr := unsafe.Pointer(C.domainQemuMonitorEventCallbackHelper) var cdom C.virDomainPtr if dom != nil { cdom = dom.ptr } + var err C.virError ret := C.virConnectDomainQemuMonitorEventRegisterWrapper(c.ptr, cdom, cEvent, - C.virConnectDomainQemuMonitorEventCallback(callbackPtr), C.long(goCallBackId), - C.uint(flags)) - if ret == -1 { + C.uint(flags), &err) + if ret < 0 { freeCallbackId(goCallBackId) - return 0, GetLastError() + return 0, makeError(&err) } return int(ret), nil } @@ -179,8 +180,10 @@ func (c *Connect) DomainQemuEventDeregister(callbackId int) error { } // Deregister the callback - if i := int(C.virConnectDomainQemuMonitorEventDeregisterWrapper(c.ptr, C.int(callbackId))); i != 0 { - return GetLastError() + var err C.virError + ret := int(C.virConnectDomainQemuMonitorEventDeregisterWrapper(c.ptr, C.int(callbackId), &err)) + if ret < 0 { + return makeError(&err) } return nil } diff --git a/qemu_wrapper.go b/qemu_wrapper.go index 1dda84d..20089d2 100644 --- a/qemu_wrapper.go +++ b/qemu_wrapper.go @@ -45,26 +45,89 @@ void domainQemuMonitorEventCallbackHelper(virConnectPtr c, virDomainPtr d, domainQemuMonitorEventCallback(c, d, event, secs, micros, details, (int)(intptr_t)data); } -int virConnectDomainQemuMonitorEventRegisterWrapper(virConnectPtr c, virDomainPtr d, - const char *event, virConnectDomainQemuMonitorEventCallback cb, - long goCallbackId, unsigned int flags) { + +int +virConnectDomainQemuMonitorEventDeregisterWrapper(virConnectPtr conn, + int callbackID, + virErrorPtr err) +{ #if LIBVIR_VERSION_NUMBER < 1002003 assert(0); // Caller should have checked version #else - void* id = (void*)goCallbackId; - return virConnectDomainQemuMonitorEventRegister(c, d, event, cb, id, freeGoCallbackHelper, flags); + int ret = virConnectDomainQemuMonitorEventDeregister(conn, callbackID); + if (ret < 0) { + virCopyLastError(err); + } + return ret; #endif } -int virConnectDomainQemuMonitorEventDeregisterWrapper(virConnectPtr conn, - int callbackID) + +int +virConnectDomainQemuMonitorEventRegisterWrapper(virConnectPtr conn, + virDomainPtr dom, + const char *event, + long goCallbackId, + unsigned int flags, + virErrorPtr err) { #if LIBVIR_VERSION_NUMBER < 1002003 assert(0); // Caller should have checked version #else - return virConnectDomainQemuMonitorEventDeregister(conn, callbackID); + void *id = (void*)goCallbackId; + int ret = virConnectDomainQemuMonitorEventRegister(conn, dom, event, domainQemuMonitorEventCallbackHelper, + id, freeGoCallbackHelper, flags); + if (ret < 0) { + virCopyLastError(err); + } + return ret; #endif } + +char * +virDomainQemuAgentCommandWrapper(virDomainPtr domain, + const char *cmd, + int timeout, + unsigned int flags, + virErrorPtr err) +{ + char * ret = virDomainQemuAgentCommand(domain, cmd, timeout, flags); + if (!ret) { + virCopyLastError(err); + } + return ret; +} + + +virDomainPtr +virDomainQemuAttachWrapper(virConnectPtr conn, + unsigned int pid_value, + unsigned int flags, + virErrorPtr err) +{ + virDomainPtr ret = virDomainQemuAttach(conn, pid_value, flags); + if (!ret) { + virCopyLastError(err); + } + return ret; +} + + +int +virDomainQemuMonitorCommandWrapper(virDomainPtr domain, + const char *cmd, + char **result, + unsigned int flags, + virErrorPtr err) +{ + int ret = virDomainQemuMonitorCommand(domain, cmd, result, flags); + if (ret < 0) { + virCopyLastError(err); + } + return ret; +} + + */ import "C" diff --git a/qemu_wrapper.h b/qemu_wrapper.h index e365fbd..df389c4 100644 --- a/qemu_wrapper.h +++ b/qemu_wrapper.h @@ -42,16 +42,37 @@ domainQemuMonitorEventCallbackHelper(virConnectPtr c, void *data); int -virConnectDomainQemuMonitorEventRegisterWrapper(virConnectPtr c, - virDomainPtr d, +virConnectDomainQemuMonitorEventDeregisterWrapper(virConnectPtr conn, + int callbackID, + virErrorPtr err); + +int +virConnectDomainQemuMonitorEventRegisterWrapper(virConnectPtr conn, + virDomainPtr dom, const char *event, - virConnectDomainQemuMonitorEventCallback cb, long goCallbackId, - unsigned int flags); + unsigned int flags, + virErrorPtr err); + +char * +virDomainQemuAgentCommandWrapper(virDomainPtr domain, + const char *cmd, + int timeout, + unsigned int flags, + virErrorPtr err); + +virDomainPtr +virDomainQemuAttachWrapper(virConnectPtr conn, + unsigned int pid_value, + unsigned int flags, + virErrorPtr err); int -virConnectDomainQemuMonitorEventDeregisterWrapper(virConnectPtr conn, - int callbackID); +virDomainQemuMonitorCommandWrapper(virDomainPtr domain, + const char *cmd, + char **result, + unsigned int flags, + virErrorPtr err); #endif /* LIBVIRT_GO_DOMAIN_EVENTS_WRAPPER_H__ */ -- 2.17.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list