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é <berra...@redhat.com>
---
 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@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Reply via email to