[dpdk-dev] lib/librte_vhost: move fdset_del out of conn_mutex

Message ID 1514380252-91162-1-git-send-email-wangzhike@jd.com (mailing list archive)
State Superseded, archived
Delegated to: Yuanhan Liu
Headers

Checks

Context Check Description
ci/checkpatch warning coding style issues
ci/Intel-compilation success Compilation OK

Commit Message

王志克 Dec. 27, 2017, 1:10 p.m. UTC
  From: wang zhike <wangzhike@jd.com>

This patch fixes below race condition:
1. one thread calls: rte_vhost_driver_unregister->lock conn_mutex
   ->fdset_del->loop to check fd.busy.
2. another thread calls fdset_event_dispatch, and the busy flag is
   changed AFTER handling on the fd, i.e, rcb(). However, the rcb,
   such as vhost_user_read_cb() would try to retrieve the conn_mutex.

So issue is that the 1st thread will loop check the flag while holding
the mutex, while the 2nd thread would be blocked by mutex and can not
change the flag. Then dead lock is observed.

Signed-off-by: zhike wang <wangzhike@jd.com>
---
 lib/librte_vhost/socket.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)
  

Patch

diff --git a/lib/librte_vhost/socket.c b/lib/librte_vhost/socket.c
index 422da00..4aa2384 100644
--- a/lib/librte_vhost/socket.c
+++ b/lib/librte_vhost/socket.c
@@ -749,6 +749,9 @@  struct vhost_user_reconnect_list {
 		struct vhost_user_socket *vsocket = vhost_user.vsockets[i];
 
 		if (!strcmp(vsocket->path, path)) {
+			int del_fds[MAX_FDS];
+			int num_of_fds = 0, i;
+
 			if (vsocket->is_server) {
 				fdset_del(&vhost_user.fdset, vsocket->socket_fd);
 				close(vsocket->socket_fd);
@@ -763,7 +766,7 @@  struct vhost_user_reconnect_list {
 			     conn = next) {
 				next = TAILQ_NEXT(conn, next);
 
-				fdset_del(&vhost_user.fdset, conn->connfd);
+				del_fds[num_of_fds++] = conn->connfd;
 				RTE_LOG(INFO, VHOST_CONFIG,
 					"free connfd = %d for device '%s'\n",
 					conn->connfd, path);
@@ -778,6 +781,10 @@  struct vhost_user_reconnect_list {
 			free(vsocket->path);
 			free(vsocket);
 
+			for(i=0;i<num_of_fds;i++){
+				fdset_del(&vhost_user.fdset, del_fds[i]);
+			}
+
 			count = --vhost_user.vsocket_cnt;
 			vhost_user.vsockets[i] = vhost_user.vsockets[count];
 			vhost_user.vsockets[count] = NULL;