Commit 3788c907 authored by Dariusz Stojaczyk's avatar Dariusz Stojaczyk Committed by Daniel Verkamp
Browse files

rte_vhost: fix double free on shutdown



The vhost connection can be closed
concurrently from 2 places:
 * the connection thread itself
 * rte_vhost_driver_unregister
The connection thread will terminate
the connection if any recv error
occured. The unregister function
will terminate the connection
together with the thread.
However, there is no sychronization
between those two. The connection
thread runs in the background
without any mutex.

The rte_vhost_driver_unregister
now signals the connection thread
to terminate itself and waits
until it's killed.

Change-Id: I012e97ebb8a79edcb2c17c28b2fc7e8041bf92b3
Signed-off-by: default avatarDariusz Stojaczyk <dariuszx.stojaczyk@intel.com>
Reviewed-on: https://review.gerrithub.io/383085


Reviewed-by: default avatarPawel Wodkowski <pawelx.wodkowski@intel.com>
Reviewed-by: default avatarDaniel Verkamp <daniel.verkamp@intel.com>
Tested-by: default avatarSPDK Automated Test System <sys_sgsw@intel.com>
parent f26983fa
Loading
Loading
Loading
Loading
+8 −19
Original line number Diff line number Diff line
@@ -713,9 +713,7 @@ rte_vhost_driver_unregister(const char *path)
{
	int i;
	int count;
	struct vhost_user_connection *conn, *next;
	struct vhost_user_connection_list del_conn_list =
			TAILQ_HEAD_INITIALIZER(del_conn_list);
	struct vhost_user_connection *conn;

	pthread_mutex_lock(&vhost_user.mutex);

@@ -732,25 +730,16 @@ rte_vhost_driver_unregister(const char *path)
			}

			pthread_mutex_lock(&vsocket->conn_mutex);
			for (conn = TAILQ_FIRST(&vsocket->conn_list);
			     conn != NULL;
			     conn = next) {
				next = TAILQ_NEXT(conn, next);

				TAILQ_REMOVE(&vsocket->conn_list, conn, next);
				TAILQ_INSERT_TAIL(&del_conn_list, conn, next);
			TAILQ_FOREACH(conn, &vsocket->conn_list, next) {
				close(conn->connfd);
			}
			pthread_mutex_unlock(&vsocket->conn_mutex);

			TAILQ_FOREACH(conn, &del_conn_list, next) {
				fdset_del(&vhost_user.fdset, conn->connfd);
				RTE_LOG(INFO, VHOST_CONFIG,
					"free connfd = %d for device '%s'\n",
					conn->connfd, path);
				close(conn->connfd);
				vhost_destroy_device(conn->vid);
				free(conn);
			}
			do {
				pthread_mutex_lock(&vsocket->conn_mutex);
				conn = TAILQ_FIRST(&vsocket->conn_list);
				pthread_mutex_unlock(&vsocket->conn_mutex);
			} while (conn != NULL);

			free(vsocket->path);
			free(vsocket);