If examples/domain-events/events-c/event-test.c uses a local driver for the hyperviror and a remote driver for storage then the segfault occurs in remoteDomainEventDispatchFunc because conn->privateData is used. The problem is as follows. The doRemoteOpen function registers remoteDomainEventFired as event handle and remoteDomainEventQueueFlush as event timeout. The doRemoteOpen function is used in remoteOpen and remoteOpenSecondaryDriver. So both handlers are registered for all types of remote drivers, but remoteDomainEventQueueFlush always uses conn->privateData. That's wrong when remoteDomainEventQueueFlush is called for any other driver than the hypervisor driver, it should use conn->storagePrivateData for the storage driver for example. In the common case this doesn't result in a segfault because in the common case all drivers for a connection are either all remote or all local and conn->privateData and conn->storagePrivateData are the same. But in the local Xen case ('event-test xen:///' executed in Domain-0, with a libvirtd running in Domain-0) the hypervisor driver is local and the storage driver is remote. This results in a mismatch between conn->privateData and conn->storagePrivateData. Now the call to remoteDomainEventQueueFlush in the context of the storage driver results in a segfault, because it assumes that conn->privateData points to remote driver private data, but it points to Xen driver private data. To fix this, the pointer to the private driver data gets passed as opaque parameter instead of the connection pointer. Because some functions called by the event handler functions need the connection pointer for other purposes than error reporting the connection pointer is passed as member of the private remote driver data struct. Now remoteDomainEventFired and remoteDomainEventQueueFlush have the correct private data pointer for the respective calling context. --- src/remote/remote_driver.c | 16 ++++++++-------- 1 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index d6f5fce..582b85c 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -152,6 +152,7 @@ struct private_stream_data { struct private_data { virMutex lock; + virConnectPtr conn; int sock; /* Socket. */ int watch; /* File handle watch */ @@ -893,7 +894,7 @@ doRemoteOpen (virConnectPtr conn, if ((priv->watch = virEventAddHandle(priv->sock, VIR_EVENT_HANDLE_READABLE, remoteDomainEventFired, - conn, NULL)) < 0) { + priv, NULL)) < 0) { DEBUG0("virEventAddHandle failed: No addHandleImpl defined." " continuing without events."); } else { @@ -901,7 +902,7 @@ doRemoteOpen (virConnectPtr conn, DEBUG0("Adding Timeout for remote event queue flushing"); if ( (priv->eventFlushTimer = virEventAddTimeout(-1, remoteDomainEventQueueFlush, - conn, NULL)) < 0) { + priv, NULL)) < 0) { DEBUG0("virEventAddTimeout failed: No addTimeoutImpl defined. " "continuing without events."); virEventRemoveHandle(priv->watch); @@ -980,6 +981,7 @@ remoteAllocPrivateData(virConnectPtr conn) return NULL; } remoteDriverLock(priv); + priv->conn = conn; priv->localUses = 1; priv->watch = -1; priv->sock = -1; @@ -8659,8 +8661,7 @@ remoteDomainEventFired(int watch, int event, void *opaque) { - virConnectPtr conn = opaque; - struct private_data *priv = conn->privateData; + struct private_data *priv = opaque; remoteDriverLock(priv); @@ -8684,7 +8685,7 @@ remoteDomainEventFired(int watch, goto done; } - if (remoteIOHandleInput(conn, priv, 0) < 0) + if (remoteIOHandleInput(priv->conn, priv, 0) < 0) DEBUG0("Something went wrong during async message processing"); done: @@ -8708,8 +8709,7 @@ static void remoteDomainEventDispatchFunc(virConnectPtr conn, void remoteDomainEventQueueFlush(int timer ATTRIBUTE_UNUSED, void *opaque) { - virConnectPtr conn = opaque; - struct private_data *priv = conn->privateData; + struct private_data *priv = opaque; virDomainEventQueue tempQueue; remoteDriverLock(priv); @@ -8731,7 +8731,7 @@ remoteDomainEventQueueFlush(int timer ATTRIBUTE_UNUSED, void *opaque) if ( priv->callbackList->count == 0 ) { /* Tell the server when we are the last callback deregistering */ - if (call (conn, priv, 0, REMOTE_PROC_DOMAIN_EVENTS_DEREGISTER, + if (call (priv->conn, priv, 0, REMOTE_PROC_DOMAIN_EVENTS_DEREGISTER, (xdrproc_t) xdr_void, (char *) NULL, (xdrproc_t) xdr_void, (char *) NULL) == -1) VIR_WARN0("Failed to de-register events"); -- 1.6.3.3 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list