]> git.droids-corp.org - dpdk.git/commitdiff
vhost: fix crash on closing in client mode
authorTonghao Zhang <xiangxia.m.yue@gmail.com>
Fri, 27 Apr 2018 15:19:44 +0000 (08:19 -0700)
committerFerruh Yigit <ferruh.yigit@intel.com>
Mon, 14 May 2018 21:30:48 +0000 (22:30 +0100)
when rte_vhost_driver_unregister detstroy the vsocket, we
should set it to NULL after freeing it, because in client mode,
the conn may be added to reconnect thread while vsocket is
destroyed. In one case, if qemu create vhostuser port as a
server with the same unix path, the reconnect thread will
reconnect to it while vsocket is destroyed.

To fix this:
1. set vsocket to NULL after free it.
2. remove the reconnection from reconnection thread in suitable
   position.

Cc: stable@dpdk.org
Signed-off-by: Tonghao Zhang <xiangxia.m.yue@gmail.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
lib/librte_vhost/socket.c

index 4ce916dc2f2cfc4b746fb38178346b22bb5cdd2d..0399c37bc46faf8dde52d37fb64fef4d2b5acb66 100644 (file)
@@ -199,6 +199,9 @@ vhost_user_add_connection(int fd, struct vhost_user_socket *vsocket)
        struct vhost_user_connection *conn;
        int ret;
 
+       if (vsocket == NULL)
+               return;
+
        conn = malloc(sizeof(*conn));
        if (conn == NULL) {
                close(fd);
@@ -778,6 +781,20 @@ unlock_exit:
        return ret;
 }
 
+static void
+vhost_user_socket_mem_free(struct vhost_user_socket *vsocket)
+{
+       if (vsocket && vsocket->path) {
+               free(vsocket->path);
+               vsocket->path = NULL;
+       }
+
+       if (vsocket) {
+               free(vsocket);
+               vsocket = NULL;
+       }
+}
+
 /*
  * Register a new vhost-user socket; here we could act as server
  * (the default case), or client (when RTE_VHOST_USER_CLIENT) flag
@@ -808,7 +825,7 @@ rte_vhost_driver_register(const char *path, uint64_t flags)
        if (vsocket->path == NULL) {
                RTE_LOG(ERR, VHOST_CONFIG,
                        "error: failed to copy socket path string\n");
-               free(vsocket);
+               vhost_user_socket_mem_free(vsocket);
                goto out;
        }
        TAILQ_INIT(&vsocket->conn_list);
@@ -866,8 +883,7 @@ out_mutex:
                        "error: failed to destroy connection mutex\n");
        }
 out_free:
-       free(vsocket->path);
-       free(vsocket);
+       vhost_user_socket_mem_free(vsocket);
 out:
        pthread_mutex_unlock(&vhost_user.mutex);
 
@@ -914,14 +930,6 @@ rte_vhost_driver_unregister(const char *path)
                struct vhost_user_socket *vsocket = vhost_user.vsockets[i];
 
                if (!strcmp(vsocket->path, path)) {
-                       if (vsocket->is_server) {
-                               fdset_del(&vhost_user.fdset, vsocket->socket_fd);
-                               close(vsocket->socket_fd);
-                               unlink(path);
-                       } else if (vsocket->reconnect) {
-                               vhost_user_remove_reconnect(vsocket);
-                       }
-
 again:
                        pthread_mutex_lock(&vsocket->conn_mutex);
                        for (conn = TAILQ_FIRST(&vsocket->conn_list);
@@ -951,9 +959,17 @@ again:
                        }
                        pthread_mutex_unlock(&vsocket->conn_mutex);
 
+                       if (vsocket->is_server) {
+                               fdset_del(&vhost_user.fdset,
+                                               vsocket->socket_fd);
+                               close(vsocket->socket_fd);
+                               unlink(path);
+                       } else if (vsocket->reconnect) {
+                               vhost_user_remove_reconnect(vsocket);
+                       }
+
                        pthread_mutex_destroy(&vsocket->conn_mutex);
-                       free(vsocket->path);
-                       free(vsocket);
+                       vhost_user_socket_mem_free(vsocket);
 
                        count = --vhost_user.vsocket_cnt;
                        vhost_user.vsockets[i] = vhost_user.vsockets[count];