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(a)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