memif: avoid double-close of the socket on client abort with un-read data 80/43380/4
authorAndrew Yourtchenko <[email protected]>
Fri, 4 Jul 2025 16:07:27 +0000 (18:07 +0200)
committerDamjan Marion <[email protected]>
Thu, 10 Jul 2025 08:15:31 +0000 (08:15 +0000)
In some cases, there are two times the clib_file_del is called:

1) from memif_disconnect -> memif_socket_close call site in memif_master_conn_fd_error
2) the supposedly defensive code at the end of memif_master_conn_fd_error.

This was observed upon using of an artisanal memif client, which did not correctly drain the data written by VPP to the notification socket - a simple Ctrl-C in the client was enough to trivially reproduce the issue.
In real world scenario using the stock client this is expected to be a fairly narrow race condition.

The issue can be demonstrated as follows:

diff --git a/src/vlib/file.c b/src/vlib/file.c
index 286b0d1f2..29138f485 100644
--- a/src/vlib/file.c
+++ b/src/vlib/file.c
@@ -200,6 +200,8 @@ epoll:
     {
       clib_file_t *f = e->data.ptr;
       clib_error_t *err;
+      clib_warning("EPOLL: count %d, fd index: %d, events: %x", n_fds_ready, f->index, e->events);
+

       if (PREDICT_FALSE (!f->active))
        {

vlib_file_poll:203: EPOLL: count 1, fd index: 6, events: 1
vlib_file_poll:203: EPOLL: count 1, fd index: 7, events: 1
vlib_file_poll:203: EPOLL: count 1, fd index: 7, events: 4
vlib_file_poll:203: EPOLL: count 1, fd index: 7, events: 1
vlib_file_poll:203: EPOLL: count 1, fd index: 7, events: 4
vlib_file_poll:203: EPOLL: count 1, fd index: 7, events: 1
vlib_file_poll:203: EPOLL: count 1, fd index: 7, events: 4
vlib_file_poll:203: EPOLL: count 1, fd index: 7, events: 1
vlib_file_poll:203: EPOLL: count 1, fd index: 7, events: 4
vlib_file_poll:203: EPOLL: count 1, fd index: 7, events: 1
vlib_file_poll:203: EPOLL: count 1, fd index: 7, events: 4
vlib_file_poll:203: EPOLL: count 1, fd index: 7, events: 1
vlib_file_poll:203: EPOLL: count 1, fd index: 7, events: 4
vlib_file_poll:203: EPOLL: count 1, fd index: 7, events: 11
memif_plugin       [error ]: memif0/0: default_socket_recvmsg: disconnected

Failing case, where the client did not drain the data sent to it:

DBGvpp# create interface memif master
DBGvpp# set int ip address memif0/0 192.0.2.1/24
DBGvpp# set interface state memif0/0 up
DBGvpp# vlib_file_poll:203: EPOLL: count 1, fd index: 6, events: 1
vlib_file_poll:203: EPOLL: count 1, fd index: 7, events: 1
vlib_file_poll:203: EPOLL: count 1, fd index: 7, events: 4
vlib_file_poll:203: EPOLL: count 1, fd index: 7, events: 1
vlib_file_poll:203: EPOLL: count 1, fd index: 7, events: 4
vlib_file_poll:203: EPOLL: count 1, fd index: 7, events: 1
vlib_file_poll:203: EPOLL: count 1, fd index: 7, events: 4
vlib_file_poll:203: EPOLL: count 1, fd index: 7, events: 1
vlib_file_poll:203: EPOLL: count 1, fd index: 7, events: 4
vlib_file_poll:203: EPOLL: count 1, fd index: 7, events: 1
vlib_file_poll:203: EPOLL: count 1, fd index: 7, events: 4
vlib_file_poll:203: EPOLL: count 1, fd index: 7, events: 1
vlib_file_poll:203: EPOLL: count 1, fd index: 7, events: 4
vlib_file_poll:203: EPOLL: count 1, fd index: 7, events: 19
memif_plugin       [warn  ]: Error on unknown file descriptor 21
vlib/file          [error ]: vlib_file_update: epoll_ctl() failed, errno 9
/home/ayourtch/vpp/src/vppinfra/pool.h:291 (_pool_put_index) assertion `!pool_is_free_index (p, index)' fails
received signal SIGABRT, PC 0xffffa7f10a50

Type: fix
Change-Id: I13247c431605470c6a59d7d4630cefa999733107
Signed-off-by: Andrew Yourtchenko <[email protected]>
src/plugins/memif/socket.c

index c2b11fc..5890e2d 100644 (file)
@@ -629,6 +629,7 @@ memif_master_conn_fd_error (clib_file_t * uf)
       err = clib_error_return (0, "connection fd error");
       memif_disconnect (mif, err);
       clib_error_free (err);
+      return 0;
     }
   else
     {