Commit ac5d8739 authored by Daniel P. Berrangé's avatar Daniel P. Berrangé

events: fix error reporting thread safety

Create wrapper functions for each events 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: 's avatarDaniel P. Berrangé <berrange@redhat.com>
parent f297ebd7
This diff is collapsed.
......@@ -225,12 +225,35 @@ void domainEventBlockThresholdCallbackHelper(virConnectPtr conn,
domainEventBlockThresholdCallback(conn, dom, dev, path, threshold, excess, (int)(intptr_t)opaque);
}
int virConnectDomainEventRegisterAnyWrapper(virConnectPtr c, virDomainPtr d,
int eventID, virConnectDomainEventGenericCallback cb,
long goCallbackId) {
void* id = (void*)goCallbackId;
return virConnectDomainEventRegisterAny(c, d, eventID, cb, id, freeGoCallbackHelper);
int
virConnectDomainEventRegisterAnyWrapper(virConnectPtr c,
virDomainPtr d,
int eventID,
virConnectDomainEventGenericCallback cb,
long goCallbackId,
virErrorPtr err)
{
void *id = (void*)goCallbackId;
int ret = virConnectDomainEventRegisterAny(c, d, eventID, cb, id, freeGoCallbackHelper);
if (ret < 0) {
virCopyLastError(err);
}
return ret;
}
int
virConnectDomainEventDeregisterAnyWrapper(virConnectPtr conn,
int callbackID,
virErrorPtr err)
{
int ret = virConnectDomainEventDeregisterAny(conn, callbackID);
if (ret < 0) {
virCopyLastError(err);
}
return ret;
}
*/
import "C"
......@@ -196,7 +196,12 @@ virConnectDomainEventRegisterAnyWrapper(virConnectPtr c,
virDomainPtr d,
int eventID,
virConnectDomainEventGenericCallback cb,
long goCallbackId);
long goCallbackId,
virErrorPtr err);
int
virConnectDomainEventDeregisterAnyWrapper(virConnectPtr conn,
int callbackID,
virErrorPtr err);
#endif /* LIBVIRT_GO_DOMAIN_EVENTS_WRAPPER_H__ */
......@@ -44,16 +44,18 @@ const (
// See also https://libvirt.org/html/libvirt-libvirt-event.html#virEventRegisterDefaultImpl
func EventRegisterDefaultImpl() error {
if i := int(C.virEventRegisterDefaultImpl()); i != 0 {
return GetLastError()
var err C.virError
if i := int(C.virEventRegisterDefaultImplWrapper(&err)); i != 0 {
return makeError(&err)
}
return nil
}
// See also https://libvirt.org/html/libvirt-libvirt-event.html#virEventRunDefaultImpl
func EventRunDefaultImpl() error {
if i := int(C.virEventRunDefaultImpl()); i != 0 {
return GetLastError()
var err C.virError
if i := int(C.virEventRunDefaultImplWrapper(&err)); i != 0 {
return makeError(&err)
}
return nil
}
......@@ -76,9 +78,10 @@ func eventHandleCallback(watch int, fd int, events int, callbackID int) {
func EventAddHandle(fd int, events EventHandleType, callback EventHandleCallback) (int, error) {
callbackID := registerCallbackId(callback)
ret := C.virEventAddHandleWrapper((C.int)(fd), (C.int)(events), (C.int)(callbackID))
var err C.virError
ret := C.virEventAddHandleWrapper((C.int)(fd), (C.int)(events), (C.int)(callbackID), &err)
if ret == -1 {
return 0, GetLastError()
return 0, makeError(&err)
}
return int(ret), nil
......@@ -90,8 +93,14 @@ func EventUpdateHandle(watch int, events EventHandleType) {
}
// See also https://libvirt.org/html/libvirt-libvirt-event.html#virEventRemoveHandle
func EventRemoveHandle(watch int) {
C.virEventRemoveHandle((C.int)(watch))
func EventRemoveHandle(watch int) error {
var err C.virError
ret := C.virEventRemoveHandleWrapper((C.int)(watch), &err)
if ret < 0 {
return makeError(&err)
}
return nil
}
type EventTimeoutCallback func(timer int)
......@@ -112,9 +121,10 @@ func eventTimeoutCallback(timer int, callbackID int) {
func EventAddTimeout(freq int, callback EventTimeoutCallback) (int, error) {
callbackID := registerCallbackId(callback)
ret := C.virEventAddTimeoutWrapper((C.int)(freq), (C.int)(callbackID))
var err C.virError
ret := C.virEventAddTimeoutWrapper((C.int)(freq), (C.int)(callbackID), &err)
if ret == -1 {
return 0, GetLastError()
return 0, makeError(&err)
}
return int(ret), nil
......@@ -126,8 +136,14 @@ func EventUpdateTimeout(timer int, freq int) {
}
// See also https://libvirt.org/html/libvirt-libvirt-event.html#virEventRemoveTimeout
func EventRemoveTimeout(timer int) {
C.virEventRemoveTimeout((C.int)(timer))
func EventRemoveTimeout(timer int) error {
var err C.virError
ret := C.virEventRemoveTimeoutWrapper((C.int)(timer), &err)
if ret < 0 {
return makeError(&err)
}
return nil
}
type EventHandleCallbackInfo struct {
......
......@@ -39,11 +39,6 @@ static void eventAddHandleHelper(int watch, int fd, int events, void *opaque)
eventHandleCallback(watch, fd, events, (int)(intptr_t)opaque);
}
int virEventAddHandleWrapper(int fd, int events, int callbackID)
{
return virEventAddHandle(fd, events, eventAddHandleHelper, (void *)(intptr_t)callbackID, NULL);
}
void eventTimeoutCallback(int timer, int callbackID);
static void eventAddTimeoutHelper(int timer, void *opaque)
......@@ -51,11 +46,6 @@ static void eventAddTimeoutHelper(int timer, void *opaque)
eventTimeoutCallback(timer, (int)(intptr_t)opaque);
}
int virEventAddTimeoutWrapper(int freq, int callbackID)
{
return virEventAddTimeout(freq, eventAddTimeoutHelper, (void *)(intptr_t)callbackID, NULL);
}
int eventAddHandleFunc(int fd, int event, uintptr_t callback, uintptr_t opaque, uintptr_t freecb);
void eventUpdateHandleFunc(int watch, int event);
int eventRemoveHandleFunc(int watch);
......@@ -126,5 +116,78 @@ void eventTimeoutCallbackFree(uintptr_t callback, uintptr_t opaque)
}
int
virEventAddHandleWrapper(int fd,
int events,
int callbackID,
virErrorPtr err)
{
int ret = virEventAddHandle(fd, events, eventAddHandleHelper, (void *)(intptr_t)callbackID, NULL);
if (ret < 0) {
virCopyLastError(err);
}
return ret;
}
int
virEventAddTimeoutWrapper(int timeout,
int callbackID,
virErrorPtr err)
{
int ret = virEventAddTimeout(timeout, eventAddTimeoutHelper, (void *)(intptr_t)callbackID, NULL);
if (ret < 0) {
virCopyLastError(err);
}
return ret;
}
int
virEventRegisterDefaultImplWrapper(virErrorPtr err)
{
int ret = virEventRegisterDefaultImpl();
if (ret < 0) {
virCopyLastError(err);
}
return ret;
}
int
virEventRemoveHandleWrapper(int watch,
virErrorPtr err)
{
int ret = virEventRemoveHandle(watch);
if (ret < 0) {
virCopyLastError(err);
}
return ret;
}
int
virEventRemoveTimeoutWrapper(int timer,
virErrorPtr err)
{
int ret = virEventRemoveTimeout(timer);
if (ret < 0) {
virCopyLastError(err);
}
return ret;
}
int
virEventRunDefaultImplWrapper(virErrorPtr err)
{
int ret = virEventRunDefaultImpl();
if (ret < 0) {
virCopyLastError(err);
}
return ret;
}
*/
import "C"
......@@ -30,15 +30,6 @@
#include <libvirt/libvirt.h>
#include <libvirt/virterror.h>
int
virEventAddHandleWrapper(int fd,
int events,
int callbackID);
int
virEventAddTimeoutWrapper(int freq,
int callbackID);
void
virEventRegisterImplWrapper(void);
......@@ -62,4 +53,30 @@ void
eventTimeoutCallbackFree(uintptr_t callback,
uintptr_t opaque);
int
virEventAddHandleWrapper(int fd,
int events,
int callbackID,
virErrorPtr err);
int
virEventAddTimeoutWrapper(int timeout,
int callbackID,
virErrorPtr err);
int
virEventRegisterDefaultImplWrapper(virErrorPtr err);
int
virEventRemoveHandleWrapper(int watch,
virErrorPtr err);
int
virEventRemoveTimeoutWrapper(int timer,
virErrorPtr err);
int
virEventRunDefaultImplWrapper(virErrorPtr err);
#endif /* LIBVIRT_GO_EVENTS_WRAPPER_H__ */
......@@ -77,13 +77,14 @@ func (c *Connect) NetworkEventLifecycleRegister(net *Network, callback NetworkEv
if net != nil {
cnet = net.ptr
}
var err C.virError
ret := C.virConnectNetworkEventRegisterAnyWrapper(c.ptr, cnet,
C.VIR_NETWORK_EVENT_ID_LIFECYCLE,
C.virConnectNetworkEventGenericCallback(callbackPtr),
C.long(goCallBackId))
C.long(goCallBackId), &err)
if ret == -1 {
freeCallbackId(goCallBackId)
return 0, GetLastError()
return 0, makeError(&err)
}
return int(ret), nil
}
......@@ -93,8 +94,10 @@ func (c *Connect) NetworkEventDeregister(callbackId int) error {
return GetNotImplementedError("virConnectNetworkEventDeregisterAny")
}
// Deregister the callback
if i := int(C.virConnectNetworkEventDeregisterAnyWrapper(c.ptr, C.int(callbackId))); i != 0 {
return GetLastError()
var err C.virError
ret := int(C.virConnectNetworkEventDeregisterAnyWrapper(c.ptr, C.int(callbackId), &err))
if ret < 0 {
return makeError(&err)
}
return nil
}
......
......@@ -40,24 +40,38 @@ void networkEventLifecycleCallbackHelper(virConnectPtr c, virNetworkPtr d,
networkEventLifecycleCallback(c, d, event, detail, (int)(intptr_t)data);
}
int virConnectNetworkEventRegisterAnyWrapper(virConnectPtr c, virNetworkPtr d,
int eventID, virConnectNetworkEventGenericCallback cb,
long goCallbackId) {
int
virConnectNetworkEventRegisterAnyWrapper(virConnectPtr c,
virNetworkPtr d,
int eventID,
virConnectNetworkEventGenericCallback cb,
long goCallbackId,
virErrorPtr err)
{
void* id = (void*)goCallbackId;
#if LIBVIR_VERSION_NUMBER < 1002001
assert(0); // Caller should have checked version
#else
return virConnectNetworkEventRegisterAny(c, d, eventID, cb, id, freeGoCallbackHelper);
int ret = virConnectNetworkEventRegisterAny(c, d, eventID, cb, id, freeGoCallbackHelper);
if (ret < 0) {
virCopyLastError(err);
}
return ret;
#endif
}
int virConnectNetworkEventDeregisterAnyWrapper(virConnectPtr conn,
int callbackID)
int callbackID,
virErrorPtr err)
{
#if LIBVIR_VERSION_NUMBER < 1002001
assert(0); // Caller should have checked version
#else
return virConnectNetworkEventDeregisterAny(conn, callbackID);
int ret = virConnectNetworkEventDeregisterAny(conn, callbackID);
if (ret < 0) {
virCopyLastError(err);
}
return ret;
#endif
}
......
......@@ -43,18 +43,13 @@ virConnectNetworkEventRegisterAnyWrapper(virConnectPtr c,
virNetworkPtr d,
int eventID,
virConnectNetworkEventGenericCallback cb,
long goCallbackId);
int
virConnectNetworkEventRegisterAnyWrapper(virConnectPtr c,
virNetworkPtr d,
int eventID,
virConnectNetworkEventGenericCallback cb,
long goCallbackId);
long goCallbackId,
virErrorPtr err);
int
virConnectNetworkEventDeregisterAnyWrapper(virConnectPtr conn,
int callbackID);
int callbackID,
virErrorPtr err);
#endif /* LIBVIRT_GO_NETWORK_EVENTS_WRAPPER_H__ */
......@@ -94,13 +94,14 @@ func (c *Connect) NodeDeviceEventLifecycleRegister(device *NodeDevice, callback
if device != nil {
cdevice = device.ptr
}
var err C.virError
ret := C.virConnectNodeDeviceEventRegisterAnyWrapper(c.ptr, cdevice,
C.VIR_NODE_DEVICE_EVENT_ID_LIFECYCLE,
C.virConnectNodeDeviceEventGenericCallback(callbackPtr),
C.long(goCallBackId))
C.long(goCallBackId), &err)
if ret == -1 {
freeCallbackId(goCallBackId)
return 0, GetLastError()
return 0, makeError(&err)
}
return int(ret), nil
}
......@@ -113,13 +114,14 @@ func (c *Connect) NodeDeviceEventUpdateRegister(device *NodeDevice, callback Nod
if device != nil {
cdevice = device.ptr
}
var err C.virError
ret := C.virConnectNodeDeviceEventRegisterAnyWrapper(c.ptr, cdevice,
C.VIR_NODE_DEVICE_EVENT_ID_UPDATE,
C.virConnectNodeDeviceEventGenericCallback(callbackPtr),
C.long(goCallBackId))
C.long(goCallBackId), &err)
if ret == -1 {
freeCallbackId(goCallBackId)
return 0, GetLastError()
return 0, makeError(&err)
}
return int(ret), nil
}
......@@ -129,8 +131,10 @@ func (c *Connect) NodeDeviceEventDeregister(callbackId int) error {
return GetNotImplementedError("virConnectNodeDeviceEventDeregisterAny")
}
// Deregister the callback
if i := int(C.virConnectNodeDeviceEventDeregisterAnyWrapper(c.ptr, C.int(callbackId))); i != 0 {
return GetLastError()
var err C.virError
ret := int(C.virConnectNodeDeviceEventDeregisterAnyWrapper(c.ptr, C.int(callbackId), &err))
if ret < 0 {
return makeError(&err)
}
return nil
}
......
......@@ -46,24 +46,41 @@ void nodeDeviceEventGenericCallbackHelper(virConnectPtr c, virNodeDevicePtr d, v
nodeDeviceEventGenericCallback(c, d, (int)(intptr_t)data);
}
int virConnectNodeDeviceEventRegisterAnyWrapper(virConnectPtr c, virNodeDevicePtr d,
int eventID, virConnectNodeDeviceEventGenericCallback cb,
long goCallbackId) {
int
virConnectNodeDeviceEventRegisterAnyWrapper(virConnectPtr c,
virNodeDevicePtr d,
int eventID,
virConnectNodeDeviceEventGenericCallback cb,
long goCallbackId,
virErrorPtr err)
{
void* id = (void*)goCallbackId;
#if LIBVIR_VERSION_NUMBER < 2002000
assert(0); // Caller should have checked version
#else
return virConnectNodeDeviceEventRegisterAny(c, d, eventID, cb, id, freeGoCallbackHelper);
int ret = virConnectNodeDeviceEventRegisterAny(c, d, eventID, cb, id, freeGoCallbackHelper);
if (ret < 0) {
virCopyLastError(err);
}
return ret;
#endif
}
int virConnectNodeDeviceEventDeregisterAnyWrapper(virConnectPtr conn,
int callbackID)
int
virConnectNodeDeviceEventDeregisterAnyWrapper(virConnectPtr conn,
int callbackID,
virErrorPtr err)
{
#if LIBVIR_VERSION_NUMBER < 2002000
assert(0); // Caller should have checked version
#else
return virConnectNodeDeviceEventDeregisterAny(conn, callbackID);
int ret = virConnectNodeDeviceEventDeregisterAny(conn, callbackID);
if (ret < 0) {
virCopyLastError(err);
}
return ret;
#endif
}
......
......@@ -48,11 +48,13 @@ virConnectNodeDeviceEventRegisterAnyWrapper(virConnectPtr c,
virNodeDevicePtr d,
int eventID,
virConnectNodeDeviceEventGenericCallback cb,
long goCallbackId);
long goCallbackId,
virErrorPtr err);
int
virConnectNodeDeviceEventDeregisterAnyWrapper(virConnectPtr conn,
int callbackID);
int callbackID,
virErrorPtr err);
#endif /* LIBVIRT_GO_NODE_DEVICE_EVENTS_WRAPPER_H__ */
......@@ -94,13 +94,14 @@ func (c *Connect) SecretEventLifecycleRegister(secret *Secret, callback SecretEv
if secret != nil {
csecret = secret.ptr
}
var err C.virError
ret := C.virConnectSecretEventRegisterAnyWrapper(c.ptr, csecret,
C.VIR_SECRET_EVENT_ID_LIFECYCLE,
C.virConnectSecretEventGenericCallback(callbackPtr),
C.long(goCallBackId))
C.long(goCallBackId), &err)
if ret == -1 {
freeCallbackId(goCallBackId)
return 0, GetLastError()
return 0, makeError(&err)
}
return int(ret), nil
}
......@@ -116,13 +117,14 @@ func (c *Connect) SecretEventValueChangedRegister(secret *Secret, callback Secre
if secret != nil {
csecret = secret.ptr
}
var err C.virError
ret := C.virConnectSecretEventRegisterAnyWrapper(c.ptr, csecret,
C.VIR_SECRET_EVENT_ID_VALUE_CHANGED,
C.virConnectSecretEventGenericCallback(callbackPtr),
C.long(goCallBackId))
C.long(goCallBackId), &err)
if ret == -1 {
freeCallbackId(goCallBackId)
return 0, GetLastError()
return 0, makeError(&err)
}
return int(ret), nil
}
......@@ -132,8 +134,10 @@ func (c *Connect) SecretEventDeregister(callbackId int) error {
return GetNotImplementedError("virConnectSecretEventDeregisterAny")
}
// Deregister the callback
if i := int(C.virConnectSecretEventDeregisterAnyWrapper(c.ptr, C.int(callbackId))); i != 0 {
return GetLastError()
var err C.virError
ret := int(C.virConnectSecretEventDeregisterAnyWrapper(c.ptr, C.int(callbackId), &err))
if ret < 0 {
return makeError(&err)
}
return nil
}
......
......@@ -47,24 +47,39 @@ void secretEventGenericCallbackHelper(virConnectPtr c, virSecretPtr d,
secretEventGenericCallback(c, d, (int)(intptr_t)data);
}
int virConnectSecretEventRegisterAnyWrapper(virConnectPtr c, virSecretPtr d,
int eventID, virConnectSecretEventGenericCallback cb,
long goCallbackId) {
int
virConnectSecretEventRegisterAnyWrapper(virConnectPtr c,
virSecretPtr d,
int eventID,
virConnectSecretEventGenericCallback cb,
long goCallbackId,
virErrorPtr err)
{
void* id = (void*)goCallbackId;
#if LIBVIR_VERSION_NUMBER < 3000000
assert(0); // Caller should have checked version
#else
return virConnectSecretEventRegisterAny(c, d, eventID, cb, id, freeGoCallbackHelper);
int ret = virConnectSecretEventRegisterAny(c, d, eventID, cb, id, freeGoCallbackHelper);
if (ret < 0) {
virCopyLastError(err);
}
return ret;
#endif
}
int virConnectSecretEventDeregisterAnyWrapper(virConnectPtr conn,
int callbackID)
int callbackID,
virErrorPtr err)
{
#if LIBVIR_VERSION_NUMBER < 3000000
assert(0); // Caller should have checked version
#else
return virConnectSecretEventDeregisterAny(conn, callbackID);
int ret = virConnectSecretEventDeregisterAny(conn, callbackID);
if (ret < 0) {
virCopyLastError(err);
}
return ret;
#endif
}
......
......@@ -47,10 +47,12 @@ virConnectSecretEventRegisterAnyWrapper(virConnectPtr c,
virSecretPtr d,
int eventID,
virConnectSecretEventGenericCallback cb,
long goCallbackId);
long goCallbackId,
virErrorPtr err);
int
virConnectSecretEventDeregisterAnyWrapper(virConnectPtr conn,
int callbackID);
int callbackID,
virErrorPtr err);
#endif /* LIBVIRT_GO_SECRET_EVENTS_WRAPPER_H__ */
......@@ -95,13 +95,14 @@ func (c *Connect) StoragePoolEventLifecycleRegister(pool *StoragePool, callback
if pool != nil {
cpool = pool.ptr
}
var err C.virError
ret := C.virConnectStoragePoolEventRegisterAnyWrapper(c.ptr, cpool,
C.VIR_STORAGE_POOL_EVENT_ID_LIFECYCLE,
C.virConnectStoragePoolEventGenericCallback(callbackPtr),
C.long(goCallBackId))
C.long(goCallBackId), &err)
if ret == -1 {
freeCallbackId(goCallBackId)
return 0, GetLastError()
return 0, makeError(&err)
}
return int(ret), nil
}
......@@ -118,13 +119,14 @@ func (c *Connect) StoragePoolEventRefreshRegister(pool *StoragePool, callback St
if pool != nil {
cpool = pool.ptr
}
var err C.virError
ret := C.virConnectStoragePoolEventRegisterAnyWrapper(c.ptr, cpool,
C.VIR_STORAGE_POOL_EVENT_ID_REFRESH,
C.virConnectStoragePoolEventGenericCallback(callbackPtr),
C.long(goCallBackId))
C.long(goCallBackId), &err)
if ret == -1 {
freeCallbackId(goCallBackId)
return 0, GetLastError()
return 0, makeError(&err)
}
return int(ret), nil
}
......@@ -135,8 +137,10 @@ func (c *Connect) StoragePoolEventDeregister(callbackId int) error {
}
// Deregister the callback
if i := int(C.virConnectStoragePoolEventDeregisterAnyWrapper(c.ptr, C.int(callbackId))); i != 0 {
return GetLastError()
var err C.virError
ret := int(C.virConnectStoragePoolEventDeregisterAnyWrapper(c.ptr, C.int(callbackId), &err))
if ret < 0 {
return makeError(&err)
}
return nil
}
......
......@@ -47,24 +47,41 @@ void storagePoolEventGenericCallbackHelper(virConnectPtr c, virStoragePoolPtr d,
storagePoolEventGenericCallback(c, d, (int)(intptr_t)data);
}
int virConnectStoragePoolEventRegisterAnyWrapper(virConnectPtr c, virStoragePoolPtr d,
int eventID, virConnectStoragePoolEventGenericCallback cb,
long goCallbackId) {
int
virConnectStoragePoolEventRegisterAnyWrapper(virConnectPtr c,
virStoragePoolPtr d,
int eventID,
virConnectStoragePoolEventGenericCallback cb,
long goCallbackId,
virErrorPtr err)
{
#if LIBVIR_VERSION_NUMBER < 2000000
assert(0); // Caller should have checked version
#else
void* id = (void*)goCallbackId;
return virConnectStoragePoolEventRegisterAny(c, d, eventID, cb, id, freeGoCallbackHelper);
int ret = virConnectStoragePoolEventRegisterAny(c, d, eventID, cb, id, freeGoCallbackHelper);
if (ret < 0) {
virCopyLastError(err);
}
return ret;
#endif
}
int virConnectStoragePoolEventDeregisterAnyWrapper(virConnectPtr conn,
int callbackID)
int
virConnectStoragePoolEventDeregisterAnyWrapper(virConnectPtr conn,
int callbackID,
virErrorPtr err)
{
#if LIBVIR_VERSION_NUMBER < 2000000
assert(0); // Caller shouuld have checked version
#else
return virConnectStoragePoolEventDeregisterAny(conn, callbackID);
int ret = virConnectStoragePoolEventDeregisterAny(conn, callbackID);
if (ret < 0) {
virCopyLastError(err);
}
return ret;
#endif
}
......
......@@ -48,10 +48,12 @@ virConnectStoragePoolEventRegisterAnyWrapper(virConnectPtr c,
virStoragePoolPtr d,
int eventID,
virConnectStoragePoolEventGenericCallback cb,
long goCallbackId);
long goCallbackId,
virErrorPtr err);
int
virConnectStoragePoolEventDeregisterAnyWrapper(virConnectPtr conn,
int callbackID);
int callbackID,
virErrorPtr err);
#endif /* LIBVIRT_GO_STORAGE_POOL_EVENTS_WRAPPER_H__ */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment