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)
commita67d90d0975d138e03ffc7a442354a63a66ddc3d
treeeb21d9ba15d39a8dc03e05d7d6f427baa08da662
parent10df6146f3e5628a8f3458be24c2796cdd736ec1
memif: avoid double-close of the socket on client abort with un-read data

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