[libvirt] [PATCH] Fix connection to already running session libvirtd

Christophe Fergeau cfergeau at redhat.com
Fri Aug 29 08:37:21 UTC 2014


Since 1b807f92, connecting with virsh to an already running session
libvirtd fails with:
$ virsh list --all
error: failed to connect to the hypervisor
error: no valid connection
error: Failed to connect socket to
'/run/user/1000/libvirt/libvirt-sock': Transport endpoint is already
connected

This is caused by a logic error in virNetSocketNewConnectUnix: even if
the connection to the daemon socket succeeded, we still try to spawn the
daemon and then connect to it.
This commit changes the logic to not try to spawn libvirtd if we
successfully connected to its socket.

With whitespace changes removed, this patch becomes just this:

diff --git a/src/rpc/virnetsocket.c b/src/rpc/virnetsocket.c
index f913365..79540b3 100644
--- a/src/rpc/virnetsocket.c
+++ b/src/rpc/virnetsocket.c
@@ -574,7 +574,8 @@ int virNetSocketNewConnectUNIX(const char *path,
         remoteAddr.data.un.sun_path[0] = '\0';

  retry:
-    if (connect(fd, &remoteAddr.data.sa, remoteAddr.len) < 0 &&
     !spawnDaemon) {
+    if (connect(fd, &remoteAddr.data.sa, remoteAddr.len) < 0) {
+        if (!spawnDaemon) {
             virReportSystemError(errno, _("Failed to connect socket to
'%s'"),
                                  path);
             goto error;
@@ -634,6 +635,7 @@ int virNetSocketNewConnectUNIX(const char *path,
             if (virNetSocketForkDaemon(binary, passfd) < 0)
                 goto error;
         }
+    }

     localAddr.len = sizeof(localAddr.data);
     if (getsockname(fd, &localAddr.data.sa, &localAddr.len) < 0) {
---
 src/rpc/virnetsocket.c | 102 +++++++++++++++++++++++++------------------------
 1 file changed, 52 insertions(+), 50 deletions(-)

diff --git a/src/rpc/virnetsocket.c b/src/rpc/virnetsocket.c
index 79258ef..8fc5d80 100644
--- a/src/rpc/virnetsocket.c
+++ b/src/rpc/virnetsocket.c
@@ -573,65 +573,67 @@ int virNetSocketNewConnectUNIX(const char *path,
         remoteAddr.data.un.sun_path[0] = '\0';
 
  retry:
-    if (connect(fd, &remoteAddr.data.sa, remoteAddr.len) < 0 && !spawnDaemon) {
-        virReportSystemError(errno, _("Failed to connect socket to '%s'"),
-                             path);
-        goto error;
-    } else if (spawnDaemon) {
-        int status = 0;
-        pid_t pid = 0;
-
-        if ((passfd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
-            virReportSystemError(errno, "%s", _("Failed to create socket"));
+    if (connect(fd, &remoteAddr.data.sa, remoteAddr.len) < 0) {
+        if (!spawnDaemon) {
+            virReportSystemError(errno, _("Failed to connect socket to '%s'"),
+                                 path);
             goto error;
-        }
+        } else if (spawnDaemon) {
+            int status = 0;
+            pid_t pid = 0;
 
-        /*
-         * We have to fork() here, because umask() is set
-         * per-process, chmod() is racy and fchmod() has undefined
-         * behaviour on sockets according to POSIX, so it doesn't
-         * work outside Linux.
-         */
-        if ((pid = virFork()) < 0)
-            goto error;
+            if ((passfd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
+                virReportSystemError(errno, "%s", _("Failed to create socket"));
+                goto error;
+            }
 
-        if (pid == 0) {
-            umask(0077);
-            if (bind(passfd, &remoteAddr.data.sa, remoteAddr.len) < 0)
-                _exit(EXIT_FAILURE);
+            /*
+             * We have to fork() here, because umask() is set
+             * per-process, chmod() is racy and fchmod() has undefined
+             * behaviour on sockets according to POSIX, so it doesn't
+             * work outside Linux.
+             */
+            if ((pid = virFork()) < 0)
+                goto error;
 
-            _exit(EXIT_SUCCESS);
-        }
+            if (pid == 0) {
+                umask(0077);
+                if (bind(passfd, &remoteAddr.data.sa, remoteAddr.len) < 0)
+                    _exit(EXIT_FAILURE);
 
-        if (virProcessWait(pid, &status, false) < 0)
-            goto error;
+                _exit(EXIT_SUCCESS);
+            }
 
-        if (status != EXIT_SUCCESS) {
-            /*
-             * OK, so the subprocces failed to bind() the socket.  This may mean
-             * that another daemon was starting at the same time and succeeded
-             * with its bind().  So we'll try connecting again, but this time
-             * without spawning the daemon.
-             */
-            spawnDaemon = false;
-            goto retry;
-        }
+            if (virProcessWait(pid, &status, false) < 0)
+                goto error;
 
-        if (listen(passfd, 0) < 0) {
-            virReportSystemError(errno, "%s",
-                                 _("Failed to listen on socket that's about "
-                                   "to be passed to the daemon"));
-            goto error;
-        }
+            if (status != EXIT_SUCCESS) {
+                /*
+                 * OK, so the subprocces failed to bind() the socket.  This may mean
+                 * that another daemon was starting at the same time and succeeded
+                 * with its bind().  So we'll try connecting again, but this time
+                 * without spawning the daemon.
+                 */
+                spawnDaemon = false;
+                goto retry;
+            }
 
-        if (connect(fd, &remoteAddr.data.sa, remoteAddr.len) < 0) {
-            virReportSystemError(errno, _("Failed to connect socket to '%s'"),
-                                 path);
-            goto error;
-        }
+            if (listen(passfd, 0) < 0) {
+                virReportSystemError(errno, "%s",
+                                     _("Failed to listen on socket that's about "
+                                       "to be passed to the daemon"));
+                goto error;
+            }
 
-        if (virNetSocketForkDaemon(binary, passfd) < 0)
-            goto error;
+            if (connect(fd, &remoteAddr.data.sa, remoteAddr.len) < 0) {
+                virReportSystemError(errno, _("Failed to connect socket to '%s'"),
+                                     path);
+                goto error;
+            }
+
+            if (virNetSocketForkDaemon(binary, passfd) < 0)
+                goto error;
+        }
     }
 
     localAddr.len = sizeof(localAddr.data);
-- 
1.9.3




More information about the libvir-list mailing list