[libvirt] PATCH: 14/25: Xen thread safety

Daniel P. Berrange berrange at redhat.com
Tue Jan 13 17:44:21 UTC 2009


This patch makes the various Xen drivers threadsafe by adding a
mutex lock on the xenUnifiedPrivatePtr object. The XenD driver
does not really need much locking, since it usually just calls
out to XenD. Likewise the Xen driver just makes hypercalls. Locks
are needed for libxenstore access, and the xm/inotify drivers
since they have shared state

 src/proxy_internal.c  |  173 ++++++++++++++++-----------------
 src/xen_inotify.c     |   25 +++-
 src/xen_internal.c    |   29 +++--
 src/xen_unified.c     |  176 +++++++++++++++++++++-------------
 src/xen_unified.h     |   36 +++++--
 src/xend_internal.c   |   37 ++++++-
 src/xm_internal.c     |  256 +++++++++++++++++++++++++++++++++-----------------
 src/xs_internal.c     |  130 +++++++++++++++++++------
 src/xs_internal.h     |    7 -
 tests/sexpr2xmltest.c |   19 +++
 10 files changed, 575 insertions(+), 313 deletions(-)

Daniel

diff --git a/src/proxy_internal.c b/src/proxy_internal.c
--- a/src/proxy_internal.c
+++ b/src/proxy_internal.c
@@ -33,7 +33,7 @@
 
 #define STANDALONE
 
-static int debug = 0;
+#define VIR_FROM_THIS VIR_FROM_PROXY
 
 static int xenProxyClose(virConnectPtr conn);
 static virDrvOpenStatus xenProxyOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags);
@@ -149,19 +149,18 @@ virProxyForkServer(void)
     const char *proxyarg[2];
 
     if (!proxyPath) {
-        fprintf(stderr, "failed to find libvirt_proxy\n");
+        VIR_WARN0("failed to find libvirt_proxy\n");
         return(-1);
     }
 
-    if (debug)
-        fprintf(stderr, "Asking to launch %s\n", proxyPath);
+    VIR_DEBUG("Asking to launch %s\n", proxyPath);
 
     proxyarg[0] = proxyPath;
     proxyarg[1] = NULL;
 
     if (virExec(NULL, proxyarg, NULL, NULL,
                 &pid, -1, NULL, NULL, VIR_EXEC_DAEMON) < 0)
-        fprintf(stderr, "Failed to fork libvirt_proxy\n");
+        VIR_ERROR0("Failed to fork libvirt_proxy\n");
 
     /*
      * do a waitpid on the intermediate process to avoid zombies.
@@ -226,32 +225,33 @@ retry:
         return (-1);
     }
 
-    if (debug > 0)
-        fprintf(stderr, "connected to unix socket %s via %d\n", path, fd);
+    DEBUG("connected to unix socket %s via %d\n", path, fd);
 
     return (fd);
 }
 
 /**
- * virProxyCloseClientSocket:
- * @fd: the file descriptor for the socket
+ * virProxyCloseSocket:
+ * @priv: the Xen proxy data
  *
- * Close the socket from that client
+ * Close the socket from that client. The caller must
+ * hold the lock on 'priv' before calling
  *
  * Returns 0 in case of success and -1 in case of error
  */
 static int
-virProxyCloseClientSocket(int fd) {
+virProxyCloseSocket(xenUnifiedPrivatePtr priv) {
     int ret;
 
-    if (fd < 0)
+    if (priv->proxy < 0)
         return(-1);
 
-    ret = close(fd);
+    ret = close(priv->proxy);
     if (ret != 0)
-        fprintf(stderr, _("Failed to close socket %d\n"), fd);
-    else if (debug > 0)
-        fprintf(stderr, "Closed socket %d\n", fd);
+        VIR_WARN(_("Failed to close socket %d\n"), priv->proxy);
+    else
+        VIR_DEBUG("Closed socket %d\n", priv->proxy);
+    priv->proxy = -1;
     return(ret);
 }
 
@@ -260,14 +260,13 @@ virProxyCloseClientSocket(int fd) {
  * @fd: the socket
  * @buffer: the target memory area
  * @len: the length in bytes
- * @quiet: quiet access
  *
  * Process a read from a client socket
  *
  * Returns the number of byte read or -1 in case of error.
  */
 static int
-virProxyReadClientSocket(int fd, char *buffer, int len, int quiet) {
+virProxyReadClientSocket(int fd, char *buffer, int len) {
     int ret;
 
     if ((fd < 0) || (buffer == NULL) || (len < 0))
@@ -277,18 +276,15 @@ retry:
     ret = read(fd, buffer, len);
     if (ret < 0) {
         if (errno == EINTR) {
-            if (debug > 0)
-                fprintf(stderr, "read socket %d interrupted\n", fd);
+            VIR_DEBUG("read socket %d interrupted\n", fd);
             goto retry;
         }
-        if (!quiet)
-            fprintf(stderr, _("Failed to read socket %d\n"), fd);
+        VIR_WARN("Failed to read socket %d\n", fd);
         return(-1);
     }
 
-    if (debug)
-        fprintf(stderr, "read %d bytes from socket %d\n",
-                ret, fd);
+    VIR_DEBUG("read %d bytes from socket %d\n",
+              ret, fd);
     return(ret);
 }
 
@@ -309,12 +305,11 @@ virProxyWriteClientSocket(int fd, const 
 
     ret = safewrite(fd, data, len);
     if (ret < 0) {
-        fprintf(stderr, _("Failed to write to socket %d\n"), fd);
+        VIR_WARN(_("Failed to write to socket %d\n"), fd);
         return(-1);
     }
-    if (debug)
-        fprintf(stderr, "wrote %d bytes to socket %d\n",
-                len, fd);
+    VIR_DEBUG("wrote %d bytes to socket %d\n",
+              len, fd);
 
     return(0);
 }
@@ -347,12 +342,9 @@ xenProxyClose(virConnectPtr conn)
         return -1;
     }
 
-    /* Fail silently. */
-    if (priv->proxy == -1)
-        return -1;
-
-    virProxyCloseClientSocket (priv->proxy);
-    priv->proxy = -1;
+    xenUnifiedLock(priv);
+    virProxyCloseSocket (priv);
+    xenUnifiedUnlock(priv);
 
     return 0;
 }
@@ -376,9 +368,11 @@ xenProxyCommand(virConnectPtr conn, virP
         return -1;
     }
 
+    xenUnifiedLock(priv);
+
     /* Fail silently. */
     if (priv->proxy == -1)
-        return -1;
+        goto error;
 
     /*
      * normal communication serial numbers are in 0..4095
@@ -390,62 +384,69 @@ xenProxyCommand(virConnectPtr conn, virP
     request->serial = serial;
     ret  = virProxyWriteClientSocket(priv->proxy, (const char *) request,
                                      request->len);
-    if (ret < 0)
-        return(-1);
+    if (ret < 0) {
+        if (!quiet)
+            virReportSystemError(conn, errno, "%s",
+                                 _("failed to write proxy request"));
+        goto error;
+    }
 retry:
     if (answer == NULL) {
         /* read in situ */
         ret  = virProxyReadClientSocket(priv->proxy, (char *) request,
-                                        sizeof(virProxyPacket), quiet);
-        if (ret < 0)
-            return(-1);
+                                        sizeof(virProxyPacket));
+        if (ret < 0) {
+            if (!quiet)
+                virReportSystemError(conn, errno, "%s",
+                                     _("failed to read proxy reply"));
+            goto error;
+        }
         if (ret != sizeof(virProxyPacket)) {
-            fprintf(stderr,
-                    _("Communication error with proxy: got %d bytes of %d\n"),
-                    ret, (int) sizeof(virProxyPacket));
-            xenProxyClose(conn);
-            return(-1);
+            virProxyError(conn, VIR_ERR_INTERNAL_ERROR,
+                          _("Communication error with proxy: got %d bytes of %d\n"),
+                          ret, (int) sizeof(virProxyPacket));
+            goto error;
         }
         res = request;
         if (res->len != sizeof(virProxyPacket)) {
-            fprintf(stderr,
-                    _("Communication error with proxy: expected %d bytes got %d\n"),
-                    (int) sizeof(virProxyPacket), res->len);
-            xenProxyClose(conn);
-            return(-1);
+            virProxyError(conn, VIR_ERR_INTERNAL_ERROR,
+                          _("Communication error with proxy: expected %d bytes got %d\n"),
+                          (int) sizeof(virProxyPacket), res->len);
+            goto error;
         }
     } else {
         /* read in packet provided */
         ret  = virProxyReadClientSocket(priv->proxy, (char *) answer,
-                                        sizeof(virProxyPacket), quiet);
-        if (ret < 0)
-            return(-1);
+                                        sizeof(virProxyPacket));
+        if (ret < 0) {
+            if (!quiet)
+                virReportSystemError(conn, errno, "%s",
+                                     _("failed to read proxy reply"));
+            goto error;
+        }
         if (ret != sizeof(virProxyPacket)) {
-            fprintf(stderr,
-                    _("Communication error with proxy: got %d bytes of %d\n"),
-                    ret, (int) sizeof(virProxyPacket));
-            xenProxyClose(conn);
-            return(-1);
+            virProxyError(conn, VIR_ERR_INTERNAL_ERROR,
+                          _("Communication error with proxy: got %d bytes of %d\n"),
+                          ret, (int) sizeof(virProxyPacket));
+            goto error;
         }
         res = (virProxyPacketPtr) answer;
         if ((res->len < sizeof(virProxyPacket)) ||
             (res->len > sizeof(virProxyFullPacket))) {
-            fprintf(stderr,
-                    _("Communication error with proxy: got %d bytes packet\n"),
-                    res->len);
-            xenProxyClose(conn);
-            return(-1);
+            virProxyError(conn, VIR_ERR_INTERNAL_ERROR,
+                          _("Communication error with proxy: got %d bytes packet\n"),
+                          res->len);
+            goto error;
         }
         if (res->len > sizeof(virProxyPacket)) {
             ret  = virProxyReadClientSocket(priv->proxy,
                                    (char *) &(answer->extra.arg[0]),
-                                            res->len - ret, quiet);
+                                            res->len - ret);
             if (ret != (int) (res->len - sizeof(virProxyPacket))) {
-                fprintf(stderr,
-                        _("Communication error with proxy: got %d bytes of %d\n"),
-                        ret, (int) sizeof(virProxyPacket));
-                xenProxyClose(conn);
-                return(-1);
+                virProxyError(conn, VIR_ERR_INTERNAL_ERROR,
+                              _("Communication error with proxy: got %d bytes of %d\n"),
+                              ret, (int) sizeof(virProxyPacket));
+                goto error;
             }
         }
     }
@@ -454,17 +455,22 @@ retry:
      */
     if ((res == NULL) || (res->version != PROXY_PROTO_VERSION) ||
         (res->len < sizeof(virProxyPacket))) {
-        fprintf(stderr, "%s",
-                _("Communication error with proxy: malformed packet\n"));
-        xenProxyClose(conn);
-        return(-1);
+        virProxyError(conn, VIR_ERR_INTERNAL_ERROR,
+                      _("Communication error with proxy: malformed packet\n"));
+        goto error;
     }
     if (res->serial != serial) {
-        TODO /* Asynchronous communication */
-        fprintf(stderr, _("got asynchronous packet number %d\n"), res->serial);
+        VIR_WARN(_("got asynchronous packet number %d\n"), res->serial);
         goto retry;
     }
-    return(0);
+
+    xenUnifiedUnlock(priv);
+    return 0;
+
+error:
+    virProxyCloseSocket(priv);
+    xenUnifiedUnlock(priv);
+    return -1;
 }
 
 /**
@@ -507,7 +513,6 @@ xenProxyOpen(virConnectPtr conn,
     ret = xenProxyCommand(conn, &req, NULL, 1);
     if ((ret < 0) || (req.command != VIR_PROXY_NONE)) {
             virProxyError(NULL, VIR_ERR_OPERATION_FAILED, __FUNCTION__);
-        xenProxyClose(conn);
         return(-1);
     }
     return(0);
@@ -549,7 +554,6 @@ xenProxyGetVersion(virConnectPtr conn, u
     req.len = sizeof(req);
     ret = xenProxyCommand(conn, &req, NULL, 0);
     if (ret < 0) {
-        xenProxyClose(conn);
         return(-1);
     }
     *hvVer = req.data.larg;
@@ -587,7 +591,6 @@ xenProxyListDomains(virConnectPtr conn, 
     req.len = sizeof(req);
     ret = xenProxyCommand(conn, &req, &ans, 0);
     if (ret < 0) {
-        xenProxyClose(conn);
         return(-1);
     }
     nb = ans.data.arg;
@@ -627,7 +630,6 @@ xenProxyNumOfDomains(virConnectPtr conn)
     req.len = sizeof(req);
     ret = xenProxyCommand(conn, &req, NULL, 0);
     if (ret < 0) {
-        xenProxyClose(conn);
         return(-1);
     }
     return(req.data.arg);
@@ -659,7 +661,6 @@ xenProxyDomainGetDomMaxMemory(virConnect
     req.len = sizeof(req);
     ret = xenProxyCommand(conn, &req, NULL, 0);
     if (ret < 0) {
-        xenProxyClose(conn);
         return(0);
     }
     return(req.data.larg);
@@ -724,7 +725,6 @@ xenProxyDomainGetInfo(virDomainPtr domai
     req.len = sizeof(req);
     ret = xenProxyCommand(domain->conn, &req, &ans, 0);
     if (ret < 0) {
-        xenProxyClose(domain->conn);
         return(-1);
     }
     if (ans.len != sizeof(virProxyPacket) + sizeof(virDomainInfo)) {
@@ -769,7 +769,6 @@ xenProxyLookupByID(virConnectPtr conn, i
     req.len = sizeof(req);
     ret = xenProxyCommand(conn, &req, &ans, 0);
     if (ret < 0) {
-        xenProxyClose(conn);
         return(NULL);
     }
     if (ans.data.arg == -1) {
@@ -814,7 +813,6 @@ xenProxyLookupByUUID(virConnectPtr conn,
 
     ret = xenProxyCommand(conn, (virProxyPacketPtr) &req, &req, 0);
     if (ret < 0) {
-        xenProxyClose(conn);
         return(NULL);
     }
     if (req.data.arg == -1) {
@@ -861,7 +859,6 @@ xenProxyLookupByName(virConnectPtr conn,
     strcpy(&req.extra.str[0], name);
     ret = xenProxyCommand(conn, (virProxyPacketPtr) &req, &req, 0);
     if (ret < 0) {
-        xenProxyClose(conn);
         return(NULL);
     }
     if (req.data.arg == -1) {
@@ -901,7 +898,6 @@ xenProxyNodeGetInfo(virConnectPtr conn, 
     req.len = sizeof(req);
     ret = xenProxyCommand(conn, &req, &ans, 0);
     if (ret < 0) {
-        xenProxyClose(conn);
         return(-1);
     }
     if (ans.data.arg == -1) {
@@ -941,7 +937,6 @@ xenProxyGetCapabilities (virConnectPtr c
     req.len = sizeof(req);
     ret = xenProxyCommand(conn, &req, &ans, 0);
     if (ret < 0) {
-        xenProxyClose(conn);
         return NULL;
     }
     if (ans.data.arg == -1)
@@ -995,7 +990,6 @@ xenProxyDomainDumpXML(virDomainPtr domai
     req.len = sizeof(req);
     ret = xenProxyCommand(domain->conn, &req, &ans, 0);
     if (ret < 0) {
-        xenProxyClose(domain->conn);
         return(NULL);
     }
     if (ans.len <= sizeof(virProxyPacket)) {
@@ -1044,7 +1038,6 @@ xenProxyDomainGetOSType(virDomainPtr dom
     req.len = sizeof(req);
     ret = xenProxyCommand(domain->conn, &req, &ans, 0);
     if (ret < 0) {
-        xenProxyClose(domain->conn);
         return(NULL);
     }
     if ((ans.len == sizeof(virProxyPacket)) && (ans.data.arg < 0)) {
diff --git a/src/xen_inotify.c b/src/xen_inotify.c
--- a/src/xen_inotify.c
+++ b/src/xen_inotify.c
@@ -92,11 +92,13 @@ struct xenUnifiedDriver xenInotifyDriver
 };
 
 static int
-xenInotifyXenCacheLookup(const char *filename,
+xenInotifyXenCacheLookup(virConnectPtr conn,
+                         const char *filename,
                          char **name, unsigned char *uuid) {
+    xenUnifiedPrivatePtr priv = conn->privateData;
     xenXMConfCachePtr entry;
 
-    if (!(entry = virHashLookup(xenXMGetConfigCache(), filename))) {
+    if (!(entry = virHashLookup(priv->configCache, filename))) {
         DEBUG("No config found for %s", filename);
         return -1;
     }
@@ -172,7 +174,7 @@ xenInotifyDomainLookup(virConnectPtr con
                        char **name, unsigned char *uuid) {
     xenUnifiedPrivatePtr priv = conn->privateData;
     if (priv->useXenConfigCache)
-        return xenInotifyXenCacheLookup(filename, name, uuid);
+        return xenInotifyXenCacheLookup(conn, filename, name, uuid);
     else
         return xenInotifyXendDomainsDirLookup(conn, filename, name, uuid);
 }
@@ -296,25 +298,27 @@ xenInotifyEvent(int watch ATTRIBUTE_UNUS
         return;
     }
 
+    xenUnifiedLock(priv);
+
 reread:
     got = read(fd, buf, sizeof(buf));
     if (got == -1) {
         if (errno == EINTR)
             goto reread;
-        return;
+        goto cleanup;
     }
 
     tmp = buf;
     while (got) {
         if (got < sizeof(struct inotify_event))
-            return; /* bad */
+            goto cleanup; /* bad */
 
         e = (struct inotify_event *)tmp;
         tmp += sizeof(struct inotify_event);
         got -= sizeof(struct inotify_event);
 
         if (got < e->len)
-            return;
+            goto cleanup;
 
         tmp += e->len;
         got -= e->len;
@@ -338,14 +342,14 @@ reread:
             if (xenInotifyRemoveDomainConfigInfo(conn, fname) < 0 ) {
                 virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
                                    "%s", _("Error adding file to config cache"));
-                return;
+                goto cleanup;
             }
         } else if (e->mask & ( IN_CREATE | IN_CLOSE_WRITE | IN_MOVED_TO) ) {
             virDomainEventPtr event;
             if (xenInotifyAddDomainConfigInfo(conn, fname) < 0 ) {
                 virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
                                    "%s", _("Error adding file to config cache"));
-                return;
+                goto cleanup;
             }
 
             event = xenInotifyDomainEventFromFile(conn, fname,
@@ -361,6 +365,9 @@ reread:
         }
 
     }
+
+cleanup:
+    xenUnifiedUnlock(priv);
 }
 
 /**
@@ -456,7 +463,7 @@ xenInotifyOpen(virConnectPtr conn ATTRIB
         DEBUG0("Failed to add inotify handle, disabling events");
     }
 
-    conn->refs++;
+    virConnectRef(conn);
     return 0;
 }
 
diff --git a/src/xen_internal.c b/src/xen_internal.c
--- a/src/xen_internal.c
+++ b/src/xen_internal.c
@@ -1330,9 +1330,14 @@ xenHypervisorDomainBlockStats (virDomain
 {
 #ifdef __linux__
     xenUnifiedPrivatePtr priv;
+    int ret;
 
     priv = (xenUnifiedPrivatePtr) dom->conn->privateData;
-    return xenLinuxDomainBlockStats (priv, dom, path, stats);
+    xenUnifiedLock(priv);
+    /* Need to lock because it hits the xenstore handle :-( */
+    ret = xenLinuxDomainBlockStats (priv, dom, path, stats);
+    xenUnifiedUnlock(priv);
+    return ret;
 #else
     virXenErrorFunc (dom->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__,
                      "block statistics not supported on this platform",
@@ -2627,8 +2632,10 @@ xenHypervisorLookupDomainByID(virConnect
     if (XEN_GETDOMAININFO_DOMAIN(dominfo) != id)
         return (NULL);
 
-
-    if (!(name = xenStoreDomainGetName(conn, id)))
+    xenUnifiedLock(priv);
+    name = xenStoreDomainGetName(conn, id);
+    xenUnifiedUnlock(priv);
+    if (!name)
         return (NULL);
 
     ret = virGetDomain(conn, name, XEN_GETDOMAININFO_UUID(dominfo));
@@ -2695,7 +2702,10 @@ xenHypervisorLookupDomainByUUID(virConne
     if (id == -1)
         return (NULL);
 
-    if (!(name = xenStoreDomainGetName(conn, id)))
+    xenUnifiedLock(priv);
+    name = xenStoreDomainGetName(conn, id);
+    xenUnifiedUnlock(priv);
+    if (!name)
         return (NULL);
 
     ret = virGetDomain(conn, name, uuid);
@@ -2928,7 +2938,6 @@ xenHypervisorNodeGetCellsFreeMemory(virC
     xen_op_v2_sys op_sys;
     int i, j, ret;
     xenUnifiedPrivatePtr priv;
-    int nbNodeCells;
 
     if (conn == NULL) {
         virXenErrorFunc (conn, VIR_ERR_INVALID_ARG, __FUNCTION__,
@@ -2936,14 +2945,15 @@ xenHypervisorNodeGetCellsFreeMemory(virC
         return -1;
     }
 
-    nbNodeCells = xenNbCells(conn);
-    if (nbNodeCells < 0) {
+    priv = conn->privateData;
+
+    if (priv->nbNodeCells < 0) {
         virXenErrorFunc (conn, VIR_ERR_XEN_CALL, __FUNCTION__,
                          "cannot determine actual number of cells",0);
         return(-1);
     }
 
-    if ((maxCells < 1) || (startCell >= nbNodeCells)) {
+    if ((maxCells < 1) || (startCell >= priv->nbNodeCells)) {
         virXenErrorFunc (conn, VIR_ERR_INVALID_ARG, __FUNCTION__,
                         "invalid argument", 0);
         return -1;
@@ -2958,7 +2968,6 @@ xenHypervisorNodeGetCellsFreeMemory(virC
         return -1;
     }
 
-    priv = (xenUnifiedPrivatePtr) conn->privateData;
     if (priv->handle < 0) {
         virXenErrorFunc (conn, VIR_ERR_INTERNAL_ERROR, __FUNCTION__,
                         "priv->handle invalid", 0);
@@ -2968,7 +2977,7 @@ xenHypervisorNodeGetCellsFreeMemory(virC
     memset(&op_sys, 0, sizeof(op_sys));
     op_sys.cmd = XEN_V2_OP_GETAVAILHEAP;
 
-    for (i = startCell, j = 0;(i < nbNodeCells) && (j < maxCells);i++,j++) {
+    for (i = startCell, j = 0;(i < priv->nbNodeCells) && (j < maxCells);i++,j++) {
         op_sys.u.availheap.node = i;
         ret = xenHypervisorDoV2Sys(priv->handle, &op_sys);
         if (ret < 0) {
diff --git a/src/xen_unified.c b/src/xen_unified.c
--- a/src/xen_unified.c
+++ b/src/xen_unified.c
@@ -56,7 +56,7 @@ xenUnifiedDomainGetVcpus (virDomainPtr d
                           unsigned char *cpumaps, int maplen);
 
 /* The five Xen drivers below us. */
-static struct xenUnifiedDriver *drivers[XEN_UNIFIED_NR_DRIVERS] = {
+static struct xenUnifiedDriver const * const drivers[XEN_UNIFIED_NR_DRIVERS] = {
     [XEN_UNIFIED_HYPERVISOR_OFFSET] = &xenHypervisorDriver,
     [XEN_UNIFIED_PROXY_OFFSET] = &xenProxyDriver,
     [XEN_UNIFIED_XEND_OFFSET] = &xenDaemonDriver,
@@ -71,14 +71,6 @@ static struct xenUnifiedDriver *drivers[
         virReportErrorHelper(conn, VIR_FROM_XEN, code, __FILE__,           \
                                __FUNCTION__, __LINE__, fmt)
 
-/*
- * Helper functions currently used in the NUMA code
- * Those variables should not be accessed directly but through helper
- * functions xenNbCells() and xenNbCpu() available to all Xen backends
- */
-static int nbNodeCells = -1;
-static int nbNodeCpus = -1;
-
 /**
  * xenNumaInit:
  * @conn: pointer to the hypervisor connection
@@ -90,42 +82,19 @@ static int nbNodeCpus = -1;
 static void
 xenNumaInit(virConnectPtr conn) {
     virNodeInfo nodeInfo;
+    xenUnifiedPrivatePtr priv;
     int ret;
 
     ret = xenUnifiedNodeGetInfo(conn, &nodeInfo);
     if (ret < 0)
         return;
-    nbNodeCells = nodeInfo.nodes;
-    nbNodeCpus = nodeInfo.cpus;
+
+    priv = conn->privateData;
+
+    priv->nbNodeCells = nodeInfo.nodes;
+    priv->nbNodeCpus = nodeInfo.cpus;
 }
 
-/**
- * xenNbCells:
- * @conn: pointer to the hypervisor connection
- *
- * Number of NUMA cells present in the actual Node
- *
- * Returns the number of NUMA cells available on that Node
- */
-int xenNbCells(virConnectPtr conn) {
-    if (nbNodeCells < 0)
-        xenNumaInit(conn);
-    return(nbNodeCells);
-}
-
-/**
- * xenNbCpus:
- * @conn: pointer to the hypervisor connection
- *
- * Number of CPUs present in the actual Node
- *
- * Returns the number of CPUs available on that Node
- */
-int xenNbCpus(virConnectPtr conn) {
-    if (nbNodeCpus < 0)
-        xenNumaInit(conn);
-    return(nbNodeCpus);
-}
 
 /**
  * xenDomainUsedCpus:
@@ -141,7 +110,7 @@ char *
 xenDomainUsedCpus(virDomainPtr dom)
 {
     char *res = NULL;
-    int nb_cpu, ncpus;
+    int ncpus;
     int nb_vcpu;
     char *cpulist = NULL;
     unsigned char *cpumap = NULL;
@@ -150,12 +119,14 @@ xenDomainUsedCpus(virDomainPtr dom)
     int n, m;
     virVcpuInfoPtr cpuinfo = NULL;
     virNodeInfo nodeinfo;
+    xenUnifiedPrivatePtr priv;
 
     if (!VIR_IS_CONNECTED_DOMAIN(dom))
         return (NULL);
 
-    nb_cpu = xenNbCpus(dom->conn);
-    if (nb_cpu <= 0)
+    priv = dom->conn->privateData;
+
+    if (priv->nbNodeCpus <= 0)
         return(NULL);
     nb_vcpu = xenUnifiedDomainGetMaxVcpus(dom);
     if (nb_vcpu <= 0)
@@ -163,7 +134,7 @@ xenDomainUsedCpus(virDomainPtr dom)
     if (xenUnifiedNodeGetInfo(dom->conn, &nodeinfo) < 0)
         return(NULL);
 
-    if (VIR_ALLOC_N(cpulist, nb_cpu) < 0)
+    if (VIR_ALLOC_N(cpulist, priv->nbNodeCpus) < 0)
         goto done;
     if (VIR_ALLOC_N(cpuinfo, nb_vcpu) < 0)
         goto done;
@@ -175,19 +146,19 @@ xenDomainUsedCpus(virDomainPtr dom)
     if ((ncpus = xenUnifiedDomainGetVcpus(dom, cpuinfo, nb_vcpu,
                                           cpumap, cpumaplen)) >= 0) {
         for (n = 0 ; n < ncpus ; n++) {
-            for (m = 0 ; m < nb_cpu; m++) {
+            for (m = 0 ; m < priv->nbNodeCpus; m++) {
                 if ((cpulist[m] == 0) &&
                     (VIR_CPU_USABLE(cpumap, cpumaplen, n, m))) {
                     cpulist[m] = 1;
                     nb++;
                     /* if all CPU are used just return NULL */
-                    if (nb == nb_cpu)
+                    if (nb == priv->nbNodeCpus)
                         goto done;
 
                 }
             }
         }
-        res = virDomainCpuSetFormat(dom->conn, cpulist, nb_cpu);
+        res = virDomainCpuSetFormat(dom->conn, cpulist, priv->nbNodeCpus);
     }
 
 done:
@@ -267,13 +238,22 @@ xenUnifiedOpen (virConnectPtr conn, virC
         xenUnifiedError (NULL, VIR_ERR_NO_MEMORY, "allocating private data");
         return VIR_DRV_OPEN_ERROR;
     }
-    conn->privateData = priv;
+    if (virMutexInit(&priv->lock) < 0) {
+        xenUnifiedError (NULL, VIR_ERR_INTERNAL_ERROR,
+                         _("cannot initialise mutex"));
+        VIR_FREE(priv);
+        return VIR_DRV_OPEN_ERROR;
+    }
 
     /* Allocate callback list */
     if (VIR_ALLOC(cbList) < 0) {
         xenUnifiedError (NULL, VIR_ERR_NO_MEMORY, "allocating callback list");
+        virMutexDestroy(&priv->lock);
+        VIR_FREE(priv);
         return VIR_DRV_OPEN_ERROR;
     }
+    conn->privateData = priv;
+
     priv->domainEventCallbacks = cbList;
 
     priv->handle = -1;
@@ -344,6 +324,8 @@ xenUnifiedOpen (virConnectPtr conn, virC
         }
     }
 
+    xenNumaInit(conn);
+
     if (!(priv->caps = xenHypervisorMakeCapabilities(conn))) {
         DEBUG0("Failed to make capabilities");
         goto fail;
@@ -368,7 +350,9 @@ clean:
     DEBUG0("Failed to activate a mandatory sub-driver");
     for (i = 0 ; i < XEN_UNIFIED_NR_DRIVERS ; i++)
         if (priv->opened[i]) drivers[i]->close(conn);
+    virMutexDestroy(&priv->lock);
     VIR_FREE(priv);
+    conn->privateData = NULL;
     return ret;
 }
 
@@ -388,7 +372,8 @@ xenUnifiedClose (virConnectPtr conn)
         if (priv->opened[i] && drivers[i]->close)
             (void) drivers[i]->close (conn);
 
-    free (conn->privateData);
+    virMutexDestroy(&priv->lock);
+    VIR_FREE(conn->privateData);
     conn->privateData = NULL;
 
     return 0;
@@ -497,17 +482,15 @@ xenUnifiedNodeGetInfo (virConnectPtr con
 static char *
 xenUnifiedGetCapabilities (virConnectPtr conn)
 {
-    GET_PRIVATE(conn);
-    int i;
-    char *ret;
+    xenUnifiedPrivatePtr priv = conn->privateData;
+    char *xml;
 
-    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
-        if (priv->opened[i] && drivers[i]->getCapabilities) {
-            ret = drivers[i]->getCapabilities (conn);
-            if (ret) return ret;
-        }
+    if (!(xml = virCapabilitiesFormatXML(priv->caps))) {
+        virReportOOMError(conn);
+        return NULL;
+    }
 
-    return NULL;
+    return xml;
 }
 
 static int
@@ -1019,7 +1002,9 @@ xenUnifiedDomainDumpXML (virDomainPtr do
     } else {
         if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
             char *cpus, *res;
+            xenUnifiedLock(priv);
             cpus = xenDomainUsedCpus(dom);
+            xenUnifiedUnlock(priv);
             res = xenDaemonDomainDumpXML(dom, flags, cpus);
             VIR_FREE(cpus);
             return(res);
@@ -1363,14 +1348,20 @@ xenUnifiedDomainEventRegister (virConnec
                                void (*freefunc)(void *))
 {
     GET_PRIVATE (conn);
+    int ret;
+
+    xenUnifiedLock(priv);
     if (priv->xsWatch == -1) {
         xenUnifiedError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+        xenUnifiedUnlock(priv);
         return -1;
     }
 
-    conn->refs++;
-    return virDomainEventCallbackListAdd(conn, priv->domainEventCallbacks,
-                                         callback, opaque, freefunc);
+    virConnectRef(conn);
+    ret = virDomainEventCallbackListAdd(conn, priv->domainEventCallbacks,
+                                        callback, opaque, freefunc);
+    xenUnifiedUnlock(priv);
+    return ret;
 }
 
 static int
@@ -1379,14 +1370,22 @@ xenUnifiedDomainEventDeregister (virConn
 {
     int ret;
     GET_PRIVATE (conn);
+
+    xenUnifiedLock(priv);
     if (priv->xsWatch == -1) {
         xenUnifiedError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+        xenUnifiedUnlock(priv);
         return -1;
     }
 
-    ret = virDomainEventCallbackListRemove(conn, priv->domainEventCallbacks,
-                                            callback);
+    if (priv->domainEventDispatching)
+        ret = virDomainEventCallbackListMarkDelete(conn, priv->domainEventCallbacks,
+                                                   callback);
+    else
+        ret = virDomainEventCallbackListRemove(conn, priv->domainEventCallbacks,
+                                               callback);
     virUnrefConnect(conn);
+    xenUnifiedUnlock(priv);
     return ret;
 }
 
@@ -1573,21 +1572,66 @@ xenUnifiedRemoveDomainInfo(xenUnifiedDom
     return -1;
 }
 
+static void
+xenUnifiedDomainEventDispatchFunc(virConnectPtr conn,
+                                  virDomainEventPtr event,
+                                  virConnectDomainEventCallback cb,
+                                  void *cbopaque,
+                                  void *opaque)
+{
+    xenUnifiedPrivatePtr priv = opaque;
+
+    /*
+     * Release the lock while the callback is running so that
+     * we're re-entrant safe for callback work - the callback
+     * may want to invoke other virt functions & we have already
+     * protected the one piece of state we have - the callback
+     * list
+     */
+    xenUnifiedUnlock(priv);
+    virDomainEventDispatchDefaultFunc(conn, event, cb, cbopaque, NULL);
+    xenUnifiedLock(priv);
+}
+
 /**
  * xenUnifiedDomainEventDispatch:
+ * @priv: the connection to dispatch events on
+ * @event: the event to dispatch
  *
  * Dispatch domain events to registered callbacks
  *
+ * The caller must hold the lock in 'priv' before invoking
+ *
  */
 void xenUnifiedDomainEventDispatch (xenUnifiedPrivatePtr priv,
                                     virDomainEventPtr event)
 {
-    if (!priv || !priv->domainEventCallbacks)
+    if (!priv)
         return;
 
-    virDomainEventDispatch(event,
-                           priv->domainEventCallbacks,
-                           virDomainEventDispatchDefaultFunc,
-                           NULL);
+    priv->domainEventDispatching = 1;
+
+    if (priv->domainEventCallbacks) {
+        virDomainEventDispatch(event,
+                               priv->domainEventCallbacks,
+                               xenUnifiedDomainEventDispatchFunc,
+                               priv);
+
+        /* Purge any deleted callbacks */
+        virDomainEventCallbackListPurgeMarked(priv->domainEventCallbacks);
+    }
+
     virDomainEventFree(event);
+
+    priv->domainEventDispatching = 0;
 }
+
+void xenUnifiedLock(xenUnifiedPrivatePtr priv)
+{
+    virMutexLock(&priv->lock);
+}
+
+void xenUnifiedUnlock(xenUnifiedPrivatePtr priv)
+{
+    virMutexUnlock(&priv->lock);
+}
diff --git a/src/xen_unified.h b/src/xen_unified.h
--- a/src/xen_unified.h
+++ b/src/xen_unified.h
@@ -131,6 +131,12 @@ typedef xenUnifiedDomainInfoList *xenUni
  * low-level drivers access parts of this structure.
  */
 struct _xenUnifiedPrivate {
+    virMutex lock;
+
+    /* These initial vars are initialized in Open method
+     * and readonly thereafter, so can be used without
+     * holding the lock
+     */
     virCapsPtr caps;
     int handle;			/* Xen hypervisor handle */
 
@@ -144,25 +150,36 @@ struct _xenUnifiedPrivate {
     struct sockaddr_un addr_un; /* the unix address */
     struct sockaddr_in addr_in; /* the inet address */
 
-    struct xs_handle *xshandle; /* handle to talk to the xenstore */
-
-    int proxy;                  /* fd of proxy. */
-
     /* Keep track of the drivers which opened.  We keep a yes/no flag
      * here for each driver, corresponding to the array drivers in
      * xen_unified.c.
      */
     int opened[XEN_UNIFIED_NR_DRIVERS];
 
+
+    /*
+     * Everything from this point onwards must be protected
+     * by the lock when used
+     */
+
+    struct xs_handle *xshandle; /* handle to talk to the xenstore */
+
+    int proxy;                  /* fd of proxy. */
+
+
     /* A list of xenstore watches */
     xenStoreWatchListPtr xsWatchList;
     int xsWatch;
     /* A list of active domain name/uuids */
     xenUnifiedDomainInfoListPtr activeDomainList;
 
+    /* NUMA topology info cache */
+    int nbNodeCells;
+    int nbNodeCpus;
 
     /* An list of callbacks */
     virDomainEventCallbackListPtr domainEventCallbacks;
+    int domainEventDispatching;
 
     /* Location of config files, either /etc
      * or /var/lib/xen */
@@ -188,9 +205,6 @@ struct _xenUnifiedPrivate {
 
 typedef struct _xenUnifiedPrivate *xenUnifiedPrivatePtr;
 
-
-int xenNbCells(virConnectPtr conn);
-int xenNbCpus(virConnectPtr conn);
 char *xenDomainUsedCpus(virDomainPtr dom);
 
 void xenUnifiedDomainInfoListFree(xenUnifiedDomainInfoListPtr info);
@@ -204,4 +218,12 @@ void xenUnifiedDomainEventDispatch (xenU
                                     virDomainEventPtr event);
 unsigned long xenUnifiedVersion(void);
 
+#ifndef PROXY
+void xenUnifiedLock(xenUnifiedPrivatePtr priv);
+void xenUnifiedUnlock(xenUnifiedPrivatePtr priv);
+#else
+#define xenUnifiedLock(p) do {} while(0)
+#define xenUnifiedUnlock(p) do {} while(0)
+#endif
+
 #endif /* __VIR_XEN_UNIFIED_H__ */
diff --git a/src/xend_internal.c b/src/xend_internal.c
--- a/src/xend_internal.c
+++ b/src/xend_internal.c
@@ -1964,18 +1964,25 @@ xenDaemonParseSxprGraphicsOld(virConnect
                               int hvm,
                               int xendConfigVersion)
 {
+#ifndef PROXY
+    xenUnifiedPrivatePtr priv = conn->privateData;
+#endif
     const char *tmp;
     virDomainGraphicsDefPtr graphics = NULL;
 
     if ((tmp = sexpr_fmt_node(root, "domain/image/%s/vnc", hvm ? "hvm" : "linux")) &&
         tmp[0] == '1') {
         /* Graphics device (HVM, or old (pre-3.0.4) style PV VNC config) */
-        int port = xenStoreDomainGetVNCPort(conn, def->id);
+        int port;
         const char *listenAddr = sexpr_fmt_node(root, "domain/image/%s/vnclisten", hvm ? "hvm" : "linux");
         const char *vncPasswd = sexpr_fmt_node(root, "domain/image/%s/vncpasswd", hvm ? "hvm" : "linux");
         const char *keymap = sexpr_fmt_node(root, "domain/image/%s/keymap", hvm ? "hvm" : "linux");
         const char *unused = sexpr_fmt_node(root, "domain/image/%s/vncunused", hvm ? "hvm" : "linux");
 
+        xenUnifiedLock(priv);
+        port = xenStoreDomainGetVNCPort(conn, def->id);
+        xenUnifiedUnlock(priv);
+
         if (VIR_ALLOC(graphics) < 0)
             goto no_memory;
 
@@ -2040,6 +2047,9 @@ xenDaemonParseSxprGraphicsNew(virConnect
                               virDomainDefPtr def,
                               const struct sexpr *root)
 {
+#ifndef PROXY
+    xenUnifiedPrivatePtr priv = conn->privateData;
+#endif
     virDomainGraphicsDefPtr graphics = NULL;
     const struct sexpr *cur, *node;
     const char *tmp;
@@ -2071,16 +2081,21 @@ xenDaemonParseSxprGraphicsNew(virConnect
                     !(graphics->data.sdl.xauth = strdup(xauth)))
                     goto no_memory;
             } else {
-                int port = xenStoreDomainGetVNCPort(conn, def->id);
-                if (port == -1) {
-                    // Didn't find port entry in xenstore
-                    port = sexpr_int(node, "device/vfb/vncdisplay");
-                }
+                int port;
                 const char *listenAddr = sexpr_node(node, "device/vfb/vnclisten");
                 const char *vncPasswd = sexpr_node(node, "device/vfb/vncpasswd");;
                 const char *keymap = sexpr_node(node, "device/vfb/keymap");
                 const char *unused = sexpr_node(node, "device/vfb/vncunused");
 
+                xenUnifiedLock(priv);
+                port = xenStoreDomainGetVNCPort(conn, def->id);
+                xenUnifiedUnlock(priv);
+
+                if (port == -1) {
+                    // Didn't find port entry in xenstore
+                    port = sexpr_int(node, "device/vfb/vncdisplay");
+                }
+
                 if ((unused && STREQ(unused, "1")) || port == -1) {
                     graphics->data.vnc.autoport = 1;
                     port = -1;
@@ -2137,6 +2152,9 @@ xenDaemonParseSxpr(virConnectPtr conn,
                    int xendConfigVersion,
                    const char *cpus)
 {
+#ifndef PROXY
+    xenUnifiedPrivatePtr priv = conn->privateData;
+#endif
     const char *tmp;
     virDomainDefPtr def;
     int hvm = 0;
@@ -2356,7 +2374,9 @@ xenDaemonParseSxpr(virConnectPtr conn,
         goto error;
 
     /* Character device config */
+    xenUnifiedLock(priv);
     tty = xenStoreDomainGetConsolePath(conn, def->id);
+    xenUnifiedUnlock(priv);
     if (hvm) {
         tmp = sexpr_node(root, "domain/image/hvm/serial");
         if (tmp && STRNEQ(tmp, "none")) {
@@ -5464,14 +5484,17 @@ virDomainXMLDevID(virDomainPtr domain,
                   char *ref,
                   int ref_len)
 {
+    xenUnifiedPrivatePtr priv = domain->conn->privateData;
     char *xref;
 
     if (dev->type == VIR_DOMAIN_DEVICE_DISK) {
         strcpy(class, "vbd");
         if (dev->data.disk->dst == NULL)
             return -1;
+        xenUnifiedLock(priv);
         xref = xenStoreDomainGetDiskID(domain->conn, domain->id,
                                        dev->data.disk->dst);
+        xenUnifiedUnlock(priv);
         if (xref == NULL)
             return -1;
 
@@ -5487,8 +5510,10 @@ virDomainXMLDevID(virDomainPtr domain,
 
         strcpy(class, "vif");
 
+        xenUnifiedLock(priv);
         xref = xenStoreDomainGetNetworkID(domain->conn, domain->id,
                                           mac);
+        xenUnifiedUnlock(priv);
         if (xref == NULL)
             return -1;
 
diff --git a/src/xm_internal.c b/src/xm_internal.c
--- a/src/xm_internal.c
+++ b/src/xm_internal.c
@@ -339,6 +339,11 @@ xenXMConfigSaveFile(virConnectPtr conn, 
     return ret;
 }
 
+
+/*
+ * Caller must hold the lock on 'conn->privateData' before
+ * calling this funtion
+ */
 int
 xenXMConfigCacheRemoveFile(virConnectPtr conn,
                            const char *filename)
@@ -359,6 +364,10 @@ xenXMConfigCacheRemoveFile(virConnectPtr
 }
 
 
+/*
+ * Caller must hold the lock on 'conn->privateData' before
+ * calling this funtion
+ */
 int
 xenXMConfigCacheAddFile(virConnectPtr conn, const char *filename)
 {
@@ -452,10 +461,14 @@ xenXMConfigCacheAddFile(virConnectPtr co
 }
 
 /* This method is called by various methods to scan /etc/xen
-   (or whatever directory was set by  LIBVIRT_XM_CONFIG_DIR
-   environment variable) and process any domain configs. It
-   has rate-limited so never rescans more frequently than
-   once every X seconds */
+ * (or whatever directory was set by  LIBVIRT_XM_CONFIG_DIR
+ * environment variable) and process any domain configs. It
+ * has rate-limited so never rescans more frequently than
+ * once every X seconds
+ *
+ * Caller must hold the lock on 'conn->privateData' before
+ * calling this funtion
+ */
 int xenXMConfigCacheRefresh (virConnectPtr conn) {
     xenUnifiedPrivatePtr priv = conn->privateData;
     DIR *dh;
@@ -613,12 +626,13 @@ int xenXMDomainGetInfo(virDomainPtr doma
         return (-1);
 
     priv = domain->conn->privateData;
+    xenUnifiedLock(priv);
 
     if (!(filename = virHashLookup(priv->nameConfigMap, domain->name)))
-        return (-1);
+        goto error;
 
     if (!(entry = virHashLookup(priv->configCache, filename)))
-        return (-1);
+        goto error;
 
     memset(info, 0, sizeof(virDomainInfo));
     info->maxMem = entry->def->maxmem;
@@ -627,8 +641,12 @@ int xenXMDomainGetInfo(virDomainPtr doma
     info->state = VIR_DOMAIN_SHUTOFF;
     info->cpuTime = 0;
 
+    xenUnifiedUnlock(priv);
     return (0);
 
+error:
+    xenUnifiedUnlock(priv);
+    return -1;
 }
 
 #define MAX_VFB 1024
@@ -1285,6 +1303,7 @@ char *xenXMDomainDumpXML(virDomainPtr do
     xenUnifiedPrivatePtr priv = domain->conn->privateData;
     const char *filename;
     xenXMConfCachePtr entry;
+    char *ret = NULL;
 
     if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
         xenXMError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
@@ -1295,14 +1314,19 @@ char *xenXMDomainDumpXML(virDomainPtr do
         return (NULL);
 
     priv = domain->conn->privateData;
+    xenUnifiedLock(priv);
 
     if (!(filename = virHashLookup(priv->nameConfigMap, domain->name)))
-        return (NULL);
+        goto cleanup;
 
     if (!(entry = virHashLookup(priv->configCache, filename)))
-        return (NULL);
+        goto cleanup;
 
-    return virDomainDefFormat(domain->conn, entry->def, flags);
+    ret = virDomainDefFormat(domain->conn, entry->def, flags);
+
+cleanup:
+    xenUnifiedUnlock(priv);
+    return ret;
 }
 
 
@@ -1313,6 +1337,7 @@ int xenXMDomainSetMemory(virDomainPtr do
     xenUnifiedPrivatePtr priv;
     const char *filename;
     xenXMConfCachePtr entry;
+    int ret = -1;
 
     if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
         xenXMError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
@@ -1327,12 +1352,13 @@ int xenXMDomainSetMemory(virDomainPtr do
         return (-1);
 
     priv = domain->conn->privateData;
+    xenUnifiedLock(priv);
 
     if (!(filename = virHashLookup(priv->nameConfigMap, domain->name)))
-        return (-1);
+        goto cleanup;
 
     if (!(entry = virHashLookup(priv->configCache, filename)))
-        return (-1);
+        goto cleanup;
 
     entry->def->memory = memory;
     if (entry->def->memory > entry->def->maxmem)
@@ -1342,9 +1368,12 @@ int xenXMDomainSetMemory(virDomainPtr do
      * in-memory representation of the config file. I say not!
      */
     if (xenXMConfigSaveFile(domain->conn, entry->filename, entry->def) < 0)
-        return (-1);
+        goto cleanup;
+    ret = 0;
 
-    return (0);
+cleanup:
+    xenUnifiedUnlock(priv);
+    return ret;
 }
 
 /*
@@ -1354,6 +1383,7 @@ int xenXMDomainSetMaxMemory(virDomainPtr
     xenUnifiedPrivatePtr priv;
     const char *filename;
     xenXMConfCachePtr entry;
+    int ret = -1;
 
     if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
         xenXMError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
@@ -1366,12 +1396,13 @@ int xenXMDomainSetMaxMemory(virDomainPtr
         return (-1);
 
     priv = domain->conn->privateData;
+    xenUnifiedLock(priv);
 
     if (!(filename = virHashLookup(priv->nameConfigMap, domain->name)))
-        return (-1);
+        goto cleanup;
 
     if (!(entry = virHashLookup(priv->configCache, filename)))
-        return (-1);
+        goto cleanup;
 
     entry->def->maxmem = memory;
     if (entry->def->memory > entry->def->maxmem)
@@ -1381,9 +1412,12 @@ int xenXMDomainSetMaxMemory(virDomainPtr
      * in-memory representation of the config file. I say not!
      */
     if (xenXMConfigSaveFile(domain->conn, entry->filename, entry->def) < 0)
-        return (-1);
+        goto cleanup;
+    ret = 0;
 
-    return (0);
+cleanup:
+    xenUnifiedUnlock(priv);
+    return ret;
 }
 
 /*
@@ -1393,24 +1427,30 @@ unsigned long xenXMDomainGetMaxMemory(vi
     xenUnifiedPrivatePtr priv;
     const char *filename;
     xenXMConfCachePtr entry;
+    unsigned long ret = 0;
 
     if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
         xenXMError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
                    __FUNCTION__);
-        return (-1);
+        return (0);
     }
     if (domain->id != -1)
-        return (-1);
+        return (0);
 
     priv = domain->conn->privateData;
+    xenUnifiedLock(priv);
 
     if (!(filename = virHashLookup(priv->nameConfigMap, domain->name)))
-        return (-1);
+        goto cleanup;
 
     if (!(entry = virHashLookup(priv->configCache, filename)))
-        return (-1);
+        goto cleanup;
 
-    return entry->def->maxmem;
+    ret = entry->def->maxmem;
+
+cleanup:
+    xenUnifiedUnlock(priv);
+    return ret;
 }
 
 /*
@@ -1420,6 +1460,7 @@ int xenXMDomainSetVcpus(virDomainPtr dom
     xenUnifiedPrivatePtr priv;
     const char *filename;
     xenXMConfCachePtr entry;
+    int ret = -1;
 
     if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
         xenXMError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
@@ -1432,12 +1473,13 @@ int xenXMDomainSetVcpus(virDomainPtr dom
         return (-1);
 
     priv = domain->conn->privateData;
+    xenUnifiedLock(priv);
 
     if (!(filename = virHashLookup(priv->nameConfigMap, domain->name)))
-        return (-1);
+        goto cleanup;
 
     if (!(entry = virHashLookup(priv->configCache, filename)))
-        return (-1);
+        goto cleanup;
 
     entry->def->vcpus = vcpus;
 
@@ -1445,9 +1487,12 @@ int xenXMDomainSetVcpus(virDomainPtr dom
      * in-memory representation of the config file. I say not!
      */
     if (xenXMConfigSaveFile(domain->conn, entry->filename, entry->def) < 0)
-        return (-1);
+        goto cleanup;
+    ret = 0;
 
-    return (0);
+cleanup:
+    xenUnifiedUnlock(priv);
+    return ret;
 }
 
 /**
@@ -1493,15 +1538,16 @@ int xenXMDomainPinVcpu(virDomainPtr doma
     }
 
     priv = domain->conn->privateData;
+    xenUnifiedLock(priv);
 
     if (!(filename = virHashLookup(priv->nameConfigMap, domain->name))) {
         xenXMError (domain->conn, VIR_ERR_INTERNAL_ERROR, "%s", _("virHashLookup"));
-        return -1;
+        goto cleanup;
     }
     if (!(entry = virHashLookup(priv->configCache, filename))) {
         xenXMError (domain->conn, VIR_ERR_INTERNAL_ERROR,
                     "%s", _("can't retrieve config file for domain"));
-        return -1;
+        goto cleanup;
     }
 
     /* from bit map, build character string of mapped CPU numbers */
@@ -1519,7 +1565,7 @@ int xenXMDomainPinVcpu(virDomainPtr doma
 
     if (virBufferError(&mapbuf)) {
         virReportOOMError(domain->conn);
-        return -1;
+        goto cleanup;
     }
 
     mapstr = virBufferContentAndReset(&mapbuf);
@@ -1546,6 +1592,7 @@ int xenXMDomainPinVcpu(virDomainPtr doma
  cleanup:
     VIR_FREE(mapstr);
     VIR_FREE(cpuset);
+    xenUnifiedUnlock(priv);
     return (ret);
 }
 
@@ -1556,7 +1603,7 @@ virDomainPtr xenXMDomainLookupByName(vir
     xenUnifiedPrivatePtr priv;
     const char *filename;
     xenXMConfCachePtr entry;
-    virDomainPtr ret;
+    virDomainPtr ret = NULL;
 
     if (!VIR_IS_CONNECT(conn)) {
         xenXMError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
@@ -1568,27 +1615,28 @@ virDomainPtr xenXMDomainLookupByName(vir
     }
 
     priv = conn->privateData;
+    xenUnifiedLock(priv);
 
 #ifndef WITH_XEN_INOTIFY
     if (xenXMConfigCacheRefresh (conn) < 0)
-        return (NULL);
+        goto cleanup;
 #endif
 
     if (!(filename = virHashLookup(priv->nameConfigMap, domname)))
-        return (NULL);
+        goto cleanup;
 
-    if (!(entry = virHashLookup(priv->configCache, filename))) {
-        return (NULL);
-    }
+    if (!(entry = virHashLookup(priv->configCache, filename)))
+        goto cleanup;
 
-    if (!(ret = virGetDomain(conn, domname, entry->def->uuid))) {
-        return (NULL);
-    }
+    if (!(ret = virGetDomain(conn, domname, entry->def->uuid)))
+        goto cleanup;
 
     /* Ensure its marked inactive, because may be cached
        handle to a previously active domain */
     ret->id = -1;
 
+cleanup:
+    xenUnifiedUnlock(priv);
     return (ret);
 }
 
@@ -1613,7 +1661,7 @@ virDomainPtr xenXMDomainLookupByUUID(vir
                                      const unsigned char *uuid) {
     xenUnifiedPrivatePtr priv;
     xenXMConfCachePtr entry;
-    virDomainPtr ret;
+    virDomainPtr ret = NULL;
 
     if (!VIR_IS_CONNECT(conn)) {
         xenXMError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
@@ -1625,24 +1673,25 @@ virDomainPtr xenXMDomainLookupByUUID(vir
     }
 
     priv = conn->privateData;
+    xenUnifiedLock(priv);
 
 #ifndef WITH_XEN_INOTIFY
     if (xenXMConfigCacheRefresh (conn) < 0)
-        return (NULL);
+        goto cleanup;
 #endif
 
-    if (!(entry = virHashSearch(priv->configCache, xenXMDomainSearchForUUID, (const void *)uuid))) {
-        return (NULL);
-    }
+    if (!(entry = virHashSearch(priv->configCache, xenXMDomainSearchForUUID, (const void *)uuid)))
+        goto cleanup;
 
-    if (!(ret = virGetDomain(conn, entry->def->name, uuid))) {
-        return (NULL);
-    }
+    if (!(ret = virGetDomain(conn, entry->def->name, uuid)))
+        goto cleanup;
 
     /* Ensure its marked inactive, because may be cached
        handle to a previously active domain */
     ret->id = -1;
 
+cleanup:
+    xenUnifiedUnlock(priv);
     return (ret);
 }
 
@@ -1652,7 +1701,7 @@ virDomainPtr xenXMDomainLookupByUUID(vir
  */
 int xenXMDomainCreate(virDomainPtr domain) {
     char *sexpr;
-    int ret;
+    int ret = -1;
     xenUnifiedPrivatePtr priv;
     const char *filename;
     xenXMConfCachePtr entry;
@@ -1662,43 +1711,45 @@ int xenXMDomainCreate(virDomainPtr domai
     if (domain->id != -1)
         return (-1);
 
+    xenUnifiedLock(priv);
+
     if (!(filename = virHashLookup(priv->nameConfigMap, domain->name)))
-        return (-1);
+        goto error;
 
     if (!(entry = virHashLookup(priv->configCache, filename)))
-        return (-1);
+        goto error;
 
     if (!(sexpr = xenDaemonFormatSxpr(domain->conn, entry->def, priv->xendConfigVersion))) {
         xenXMError(domain->conn, VIR_ERR_XML_ERROR,
                    "%s", _("failed to build sexpr"));
-        return (-1);
+        goto error;
     }
 
     ret = xenDaemonDomainCreateXML(domain->conn, sexpr);
     VIR_FREE(sexpr);
-    if (ret != 0) {
-        return (-1);
-    }
+    if (ret != 0)
+        goto error;
 
     if ((ret = xenDaemonDomainLookupByName_ids(domain->conn, domain->name,
-                                               entry->def->uuid)) < 0) {
-        return (-1);
-    }
+                                               entry->def->uuid)) < 0)
+        goto error;
     domain->id = ret;
 
     if ((ret = xend_wait_for_devices(domain->conn, domain->name)) < 0)
-        goto cleanup;
+        goto error;
 
     if ((ret = xenDaemonDomainResume(domain)) < 0)
-        goto cleanup;
+        goto error;
 
+    xenUnifiedUnlock(priv);
     return (0);
 
- cleanup:
+ error:
     if (domain->id != -1) {
         xenDaemonDomainDestroy(domain);
         domain->id = -1;
     }
+    xenUnifiedUnlock(priv);
     return (-1);
 }
 
@@ -2281,14 +2332,20 @@ virDomainPtr xenXMDomainDefineXML(virCon
     if (conn->flags & VIR_CONNECT_RO)
         return (NULL);
 
+    xenUnifiedLock(priv);
+
 #ifndef WITH_XEN_INOTIFY
-    if (xenXMConfigCacheRefresh (conn) < 0)
+    if (xenXMConfigCacheRefresh (conn) < 0) {
+        xenUnifiedUnlock(priv);
         return (NULL);
+    }
 #endif
 
     if (!(def = virDomainDefParseString(conn, priv->caps, xml,
-                                        VIR_DOMAIN_XML_INACTIVE)))
+                                        VIR_DOMAIN_XML_INACTIVE))) {
+        xenUnifiedUnlock(priv);
         return (NULL);
+    }
 
     if (virHashLookup(priv->nameConfigMap, def->name)) {
         /* domain exists, we will overwrite it */
@@ -2366,16 +2423,16 @@ virDomainPtr xenXMDomainDefineXML(virCon
         goto error;
     }
 
-    if (!(ret = virGetDomain(conn, def->name, def->uuid)))
-        return NULL;
+    if ((ret = virGetDomain(conn, def->name, def->uuid)))
+        ret->id = -1;
 
-    ret->id = -1;
-
+    xenUnifiedUnlock(priv);
     return (ret);
 
  error:
     VIR_FREE(entry);
     virDomainDefFree(def);
+    xenUnifiedUnlock(priv);
     return (NULL);
 }
 
@@ -2386,6 +2443,8 @@ int xenXMDomainUndefine(virDomainPtr dom
     xenUnifiedPrivatePtr priv;
     const char *filename;
     xenXMConfCachePtr entry;
+    int ret = -1;
+
     if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
         xenXMError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
                    __FUNCTION__);
@@ -2398,25 +2457,30 @@ int xenXMDomainUndefine(virDomainPtr dom
         return (-1);
 
     priv = domain->conn->privateData;
+    xenUnifiedLock(priv);
 
     if (!(filename = virHashLookup(priv->nameConfigMap, domain->name)))
-        return (-1);
+        goto cleanup;
 
     if (!(entry = virHashLookup(priv->configCache, filename)))
-        return (-1);
+        goto cleanup;
 
     if (unlink(entry->filename) < 0)
-        return (-1);
+        goto cleanup;
 
     /* Remove the name -> filename mapping */
     if (virHashRemoveEntry(priv->nameConfigMap, domain->name, NULL) < 0)
-        return(-1);
+        goto cleanup;
 
     /* Remove the config record itself */
     if (virHashRemoveEntry(priv->configCache, entry->filename, xenXMConfigFree) < 0)
-        return (-1);
+        goto cleanup;
 
-    return (0);
+    ret = 0;
+
+cleanup:
+    xenUnifiedUnlock(priv);
+    return ret;
 }
 
 struct xenXMListIteratorContext {
@@ -2450,6 +2514,7 @@ static void xenXMListIterator(const void
 int xenXMListDefinedDomains(virConnectPtr conn, char **const names, int maxnames) {
     xenUnifiedPrivatePtr priv;
     struct xenXMListIteratorContext ctx;
+    int ret = -1;
 
     if (!VIR_IS_CONNECT(conn)) {
         xenXMError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
@@ -2457,10 +2522,11 @@ int xenXMListDefinedDomains(virConnectPt
     }
 
     priv = conn->privateData;
+    xenUnifiedLock(priv);
 
 #ifndef WITH_XEN_INOTIFY
     if (xenXMConfigCacheRefresh (conn) < 0)
-        return (-1);
+        goto cleanup;
 #endif
 
     if (maxnames > virHashSize(priv->configCache))
@@ -2472,7 +2538,13 @@ int xenXMListDefinedDomains(virConnectPt
     ctx.names = names;
 
     virHashForEach(priv->nameConfigMap, xenXMListIterator, &ctx);
-    return (ctx.count);
+    ret = ctx.count;
+
+#ifndef WITH_XEN_INOTIFY
+cleanup:
+#endif
+    xenUnifiedUnlock(priv);
+    return ret;
 }
 
 /*
@@ -2481,6 +2553,7 @@ int xenXMListDefinedDomains(virConnectPt
  */
 int xenXMNumOfDefinedDomains(virConnectPtr conn) {
     xenUnifiedPrivatePtr priv;
+    int ret = -1;
 
     if (!VIR_IS_CONNECT(conn)) {
         xenXMError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
@@ -2488,13 +2561,20 @@ int xenXMNumOfDefinedDomains(virConnectP
     }
 
     priv = conn->privateData;
+    xenUnifiedLock(priv);
 
 #ifndef WITH_XEN_INOTIFY
     if (xenXMConfigCacheRefresh (conn) < 0)
-        return (-1);
+        goto cleanup;
 #endif
 
-    return virHashSize(priv->nameConfigMap);
+    ret = virHashSize(priv->nameConfigMap);
+
+#ifndef WITH_XEN_INOTIFY
+cleanup:
+#endif
+    xenUnifiedUnlock(priv);
+    return ret;
 }
 
 
@@ -2523,24 +2603,25 @@ xenXMDomainAttachDevice(virDomainPtr dom
         return -1;
     }
 
-    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
-
     if (domain->conn->flags & VIR_CONNECT_RO)
         return -1;
     if (domain->id != -1)
         return -1;
 
+    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
+    xenUnifiedLock(priv);
+
     if (!(filename = virHashLookup(priv->nameConfigMap, domain->name)))
-        return -1;
+        goto cleanup;
     if (!(entry = virHashLookup(priv->configCache, filename)))
-        return -1;
+        goto cleanup;
     def = entry->def;
 
     if (!(dev = virDomainDeviceDefParse(domain->conn,
                                         priv->caps,
                                         entry->def,
                                         xml, VIR_DOMAIN_XML_INACTIVE)))
-        return -1;
+        goto cleanup;
 
     switch (dev->type) {
     case VIR_DOMAIN_DEVICE_DISK:
@@ -2583,7 +2664,7 @@ xenXMDomainAttachDevice(virDomainPtr dom
 
  cleanup:
     virDomainDeviceDefFree(dev);
-
+    xenUnifiedUnlock(priv);
     return ret;
 }
 
@@ -2613,23 +2694,25 @@ xenXMDomainDetachDevice(virDomainPtr dom
         return -1;
     }
 
-    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
-
     if (domain->conn->flags & VIR_CONNECT_RO)
         return -1;
     if (domain->id != -1)
         return -1;
+
+    priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
+    xenUnifiedLock(priv);
+
     if (!(filename = virHashLookup(priv->nameConfigMap, domain->name)))
-        return -1;
+        goto cleanup;
     if (!(entry = virHashLookup(priv->configCache, filename)))
-        return -1;
+        goto cleanup;
     def = entry->def;
 
     if (!(dev = virDomainDeviceDefParse(domain->conn,
                                         priv->caps,
                                         entry->def,
                                         xml, VIR_DOMAIN_XML_INACTIVE)))
-        return -1;
+        goto cleanup;
 
     switch (dev->type) {
     case VIR_DOMAIN_DEVICE_DISK:
@@ -2681,6 +2764,7 @@ xenXMDomainDetachDevice(virDomainPtr dom
 
  cleanup:
     virDomainDeviceDefFree(dev);
+    xenUnifiedUnlock(priv);
     return (ret);
 }
 
diff --git a/src/xs_internal.c b/src/xs_internal.c
--- a/src/xs_internal.c
+++ b/src/xs_internal.c
@@ -37,16 +37,10 @@
 #include "xs_internal.h"
 #include "xen_internal.h" /* for xenHypervisorCheckID */
 
-#ifdef __linux__
-#define XEN_HYPERVISOR_SOCKET "/proc/xen/privcmd"
-#elif defined(__sun)
-#define XEN_HYPERVISOR_SOCKET "/dev/xen/privcmd"
-#else
-#error "unsupported platform"
-#endif
-
 #ifndef PROXY
 static char *xenStoreDomainGetOSType(virDomainPtr domain);
+static void xenStoreWatchEvent(int watch, int fd, int events, void *data);
+static void xenStoreWatchListFree(xenStoreWatchListPtr list);
 
 struct xenUnifiedDriver xenStoreDriver = {
     xenStoreOpen, /* open */
@@ -374,6 +368,7 @@ xenStoreClose(virConnectPtr conn)
 
     priv = (xenUnifiedPrivatePtr) conn->privateData;
 
+#ifndef PROXY
     if (xenStoreRemoveWatch(conn, "@introduceDomain", "introduceDomain") < 0) {
         DEBUG0("Warning, could not remove @introduceDomain watch");
         /* not fatal */
@@ -385,7 +380,6 @@ xenStoreClose(virConnectPtr conn)
     }
 
     xenStoreWatchListFree(priv->xsWatchList);
-#ifndef PROXY
     xenUnifiedDomainInfoListFree(priv->activeDomainList);
 #endif
     if (priv->xshandle == NULL)
@@ -516,17 +510,21 @@ xenStoreDomainGetMaxMemory(virDomainPtr 
 {
     char *tmp;
     unsigned long ret = 0;
+    xenUnifiedPrivatePtr priv;
 
     if (!VIR_IS_CONNECTED_DOMAIN(domain))
         return (ret);
     if (domain->id == -1)
         return(-1);
 
+    priv = domain->conn->privateData;
+    xenUnifiedLock(priv);
     tmp = virDomainDoStoreQuery(domain->conn, domain->id, "memory/target");
     if (tmp != NULL) {
         ret = (unsigned long) atol(tmp);
-        free(tmp);
+        VIR_FREE(tmp);
     }
+    xenUnifiedUnlock(priv);
     return(ret);
 }
 
@@ -589,12 +587,14 @@ xenStoreListDomains(virConnectPtr conn, 
     }
 
     priv = (xenUnifiedPrivatePtr) conn->privateData;
+
+    xenUnifiedLock(priv);
     if (priv->xshandle == NULL)
-        return(-1);
+        goto error;
 
     idlist = xs_directory (priv->xshandle, 0, "/local/domain", &num);
     if (idlist == NULL)
-        return(-1);
+        goto error;
 
     for (ret = 0, i = 0; (i < num) && (ret < maxids); i++) {
         id = strtol(idlist[i], &endptr, 10);
@@ -609,7 +609,12 @@ xenStoreListDomains(virConnectPtr conn, 
         ids[ret++] = (int) id;
     }
     free(idlist);
+    xenUnifiedUnlock(priv);
     return(ret);
+
+error:
+    xenUnifiedUnlock(priv);
+    return -1;
 }
 
 /**
@@ -694,6 +699,9 @@ done:
 int
 xenStoreDomainShutdown(virDomainPtr domain)
 {
+    int ret;
+    xenUnifiedPrivatePtr priv;
+
     if ((domain == NULL) || (domain->conn == NULL)) {
         virXenStoreError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
                          __FUNCTION__);
@@ -705,7 +713,11 @@ xenStoreDomainShutdown(virDomainPtr doma
      * this is very hackish, the domU kernel probes for a special
      * node in the xenstore and launch the shutdown command if found.
      */
-    return(virDomainDoStoreWrite(domain, "control/shutdown", "poweroff"));
+    priv = domain->conn->privateData;
+    xenUnifiedLock(priv);
+    ret = virDomainDoStoreWrite(domain, "control/shutdown", "poweroff");
+    xenUnifiedUnlock(priv);
+    return ret;
 }
 
 /**
@@ -722,6 +734,9 @@ xenStoreDomainShutdown(virDomainPtr doma
 int
 xenStoreDomainReboot(virDomainPtr domain, unsigned int flags ATTRIBUTE_UNUSED)
 {
+    int ret;
+    xenUnifiedPrivatePtr priv;
+
     if ((domain == NULL) || (domain->conn == NULL)) {
         virXenStoreError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
                          __FUNCTION__);
@@ -733,7 +748,11 @@ xenStoreDomainReboot(virDomainPtr domain
      * this is very hackish, the domU kernel probes for a special
      * node in the xenstore and launch the shutdown command if found.
      */
-    return(virDomainDoStoreWrite(domain, "control/shutdown", "reboot"));
+    priv = domain->conn->privateData;
+    xenUnifiedLock(priv);
+    ret = virDomainDoStoreWrite(domain, "control/shutdown", "reboot");
+    xenUnifiedUnlock(priv);
+    return ret;
 }
 
 /*
@@ -757,8 +776,11 @@ xenStoreDomainGetOSType(virDomainPtr dom
 
     vm = virDomainGetVM(domain);
     if (vm) {
+        xenUnifiedPrivatePtr priv = domain->conn->privateData;
+        xenUnifiedLock(priv);
         str = virDomainGetVMInfo(domain, vm, "image/ostype");
-        free(vm);
+        xenUnifiedUnlock(priv);
+        VIR_FREE(vm);
     }
 
     return (str);
@@ -773,6 +795,9 @@ xenStoreDomainGetOSType(virDomainPtr dom
  * Return the port number on which the domain is listening for VNC
  * connections.
  *
+ * The caller must hold the lock on the privateData
+ * associated with the 'conn' parameter.
+ *
  * Returns the port number, -1 in case of error
  */
 int             xenStoreDomainGetVNCPort(virConnectPtr conn, int domid) {
@@ -801,6 +826,9 @@ int             xenStoreDomainGetVNCPort
  * Returns the path to the serial console. It is the callers
  * responsibilty to free() the return string. Returns NULL
  * on error
+ *
+ * The caller must hold the lock on the privateData
+ * associated with the 'conn' parameter.
  */
 char *          xenStoreDomainGetConsolePath(virConnectPtr conn, int domid) {
   return virDomainDoStoreQuery(conn, domid, "console/tty");
@@ -814,6 +842,9 @@ char *          xenStoreDomainGetConsole
  *
  * Get the type of domain operation system.
  *
+ * The caller must hold the lock on the privateData
+ * associated with the 'conn' parameter.
+ *
  * Returns the new string or NULL in case of error, the string must be
  *         freed by the caller.
  */
@@ -858,6 +889,9 @@ xenStoreDomainGetOSTypeID(virConnectPtr 
  * Get the reference (i.e. the string number) for the device on that domain
  * which uses the given mac address
  *
+ * The caller must hold the lock on the privateData
+ * associated with the 'conn' parameter.
+ *
  * Returns the new string or NULL in case of error, the string must be
  *         freed by the caller.
  */
@@ -910,6 +944,9 @@ xenStoreDomainGetNetworkID(virConnectPtr
  * Get the reference (i.e. the string number) for the device on that domain
  * which uses the given virtual block device name
  *
+ * The caller must hold the lock on the privateData
+ * associated with the 'conn' parameter.
+ *
  * Returns the new string or NULL in case of error, the string must be
  *         freed by the caller.
  */
@@ -973,6 +1010,10 @@ xenStoreDomainGetDiskID(virConnectPtr co
     return (NULL);
 }
 
+/*
+ * The caller must hold the lock on the privateData
+ * associated with the 'conn' parameter.
+ */
 char *xenStoreDomainGetName(virConnectPtr conn,
                             int id) {
     char prop[200];
@@ -989,6 +1030,10 @@ char *xenStoreDomainGetName(virConnectPt
 }
 
 #ifndef PROXY
+/*
+ * The caller must hold the lock on the privateData
+ * associated with the 'conn' parameter.
+ */
 int xenStoreDomainGetUUID(virConnectPtr conn,
                           int id,
                           unsigned char *uuid) {
@@ -1015,9 +1060,9 @@ int xenStoreDomainGetUUID(virConnectPtr 
 
     return ret;
 }
-#endif //PROXY
 
-void xenStoreWatchListFree(xenStoreWatchListPtr list)
+static void
+xenStoreWatchListFree(xenStoreWatchListPtr list)
 {
     int i;
     for (i=0; i<list->count; i++) {
@@ -1028,6 +1073,10 @@ void xenStoreWatchListFree(xenStoreWatch
     VIR_FREE(list);
 }
 
+/*
+ * The caller must hold the lock on the privateData
+ * associated with the 'conn' parameter.
+ */
 int xenStoreAddWatch(virConnectPtr conn,
                      const char *path,
                      const char *token,
@@ -1080,6 +1129,10 @@ int xenStoreAddWatch(virConnectPtr conn,
     return xs_watch(priv->xshandle, watch->path, watch->token);
 }
 
+/*
+ * The caller must hold the lock on the privateData
+ * associated with the 'conn' parameter.
+ */
 int xenStoreRemoveWatch(virConnectPtr conn,
                         const char *path,
                         const char *token)
@@ -1122,18 +1175,17 @@ int xenStoreRemoveWatch(virConnectPtr co
                 ; /* Failure to reduce memory allocation isn't fatal */
             }
             list->count--;
-#ifndef PROXY
             virUnrefConnect(conn);
-#endif
             return 0;
         }
     }
     return -1;
 }
 
-xenStoreWatchPtr xenStoreFindWatch(xenStoreWatchListPtr list,
-                                   const char *path,
-                                   const char *token)
+static xenStoreWatchPtr
+xenStoreFindWatch(xenStoreWatchListPtr list,
+                  const char *path,
+                  const char *token)
 {
     int i;
     for (i = 0 ; i < list->count ; i++)
@@ -1144,10 +1196,11 @@ xenStoreWatchPtr xenStoreFindWatch(xenSt
     return NULL;
 }
 
-void xenStoreWatchEvent(int watch ATTRIBUTE_UNUSED,
-                        int fd ATTRIBUTE_UNUSED,
-                        int events ATTRIBUTE_UNUSED,
-                        void *data)
+static void
+xenStoreWatchEvent(int watch ATTRIBUTE_UNUSED,
+                   int fd ATTRIBUTE_UNUSED,
+                   int events ATTRIBUTE_UNUSED,
+                   void *data)
 {
     char		 **event;
     char		 *path;
@@ -1158,11 +1211,15 @@ void xenStoreWatchEvent(int watch ATTRIB
     virConnectPtr        conn = data;
     xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) conn->privateData;
     if(!priv) return;
-    if(!priv->xshandle) return;
+
+    xenUnifiedLock(priv);
+
+    if(!priv->xshandle)
+        goto cleanup;
 
     event = xs_read_watch(priv->xshandle, &stringCount);
     if (!event)
-        return;
+        goto cleanup;
 
     path  = event[XS_WATCH_PATH];
     token = event[XS_WATCH_TOKEN];
@@ -1171,10 +1228,17 @@ void xenStoreWatchEvent(int watch ATTRIB
     if( sw )
         sw->cb(conn, path, token, sw->opaque);
     VIR_FREE(event);
+
+cleanup:
+    xenUnifiedUnlock(priv);
 }
 
-#ifndef PROXY
-/* The domain callback for the @introduceDomain watch */
+
+/*
+ * The domain callback for the @introduceDomain watch
+ *
+ * The lock on 'priv' is held when calling this
+ */
 int xenStoreDomainIntroduced(virConnectPtr conn,
                              const char *path ATTRIBUTE_UNUSED,
                              const char *token ATTRIBUTE_UNUSED,
@@ -1249,7 +1313,11 @@ retry:
     return 0;
 }
 
-/* The domain callback for the @destroyDomain watch */
+/*
+ * The domain callback for the @destroyDomain watch
+ *
+ * The lock on 'priv' is held when calling this
+ */
 int xenStoreDomainReleased(virConnectPtr conn,
                             const char *path  ATTRIBUTE_UNUSED,
                             const char *token ATTRIBUTE_UNUSED,
diff --git a/src/xs_internal.h b/src/xs_internal.h
--- a/src/xs_internal.h
+++ b/src/xs_internal.h
@@ -78,8 +78,6 @@ typedef struct _xenStoreWatchList xenSto
 typedef xenStoreWatchList *xenStoreWatchListPtr;
 
 
-void            xenStoreWatchListFree(xenStoreWatchListPtr head);
-
 int             xenStoreAddWatch(virConnectPtr conn,
                                  const char *path,
                                  const char *token,
@@ -88,11 +86,6 @@ int             xenStoreAddWatch(virConn
 int             xenStoreRemoveWatch(virConnectPtr conn,
                                     const char *path,
                                     const char *token);
-xenStoreWatchPtr xenStoreFindWatch(xenStoreWatchListPtr list,
-                                  const char *path,
-                                  const char *token);
-
-void xenStoreWatchEvent(int watch, int fd, int events, void *data);
 
 /* domain events */
 int xenStoreDomainIntroduced(virConnectPtr conn,
diff --git a/tests/sexpr2xmltest.c b/tests/sexpr2xmltest.c
--- a/tests/sexpr2xmltest.c
+++ b/tests/sexpr2xmltest.c
@@ -5,7 +5,9 @@
 #include <unistd.h>
 
 #include "internal.h"
+#include "datatypes.h"
 #include "xml.h"
+#include "xen_unified.h"
 #include "xend_internal.h"
 #include "testutils.h"
 
@@ -23,6 +25,11 @@ static int testCompareFiles(const char *
   char *sexprPtr = &(sexprData[0]);
   int ret = -1;
   virDomainDefPtr def = NULL;
+  virConnectPtr conn;
+  struct _xenUnifiedPrivate priv;
+
+  conn = virGetConnect();
+  if (!conn) goto fail;
 
   if (virtTestLoadFile(xml, &xmlPtr, MAX_FILE) < 0)
       goto fail;
@@ -30,7 +37,15 @@ static int testCompareFiles(const char *
   if (virtTestLoadFile(sexpr, &sexprPtr, MAX_FILE) < 0)
       goto fail;
 
-  if (!(def = xenDaemonParseSxprString(NULL, sexprData, xendConfigVersion)))
+  memset(&priv, 0, sizeof(priv));
+  /* Many puppies died to bring you this code. */
+  priv.xendConfigVersion = xendConfigVersion;
+  conn->privateData = &priv;
+
+  if (virMutexInit(&priv.lock) < 0)
+      goto fail;
+
+  if (!(def = xenDaemonParseSxprString(conn, sexprData, xendConfigVersion)))
       goto fail;
 
   if (!(gotxml = virDomainDefFormat(NULL, def, 0)))
@@ -46,6 +61,8 @@ static int testCompareFiles(const char *
  fail:
   free(gotxml);
   virDomainDefFree(def);
+  virUnrefConnect(conn);
+  virMutexDestroy(&priv.lock);
 
   return ret;
 }

-- 
|: Red Hat, Engineering, London   -o-   http://people.redhat.com/berrange/ :|
|: http://libvirt.org  -o-  http://virt-manager.org  -o-  http://ovirt.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505  -o-  F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|




More information about the libvir-list mailing list