From c86662a213ce751354ac513a3da95117fff31845 Mon Sep 17 00:00:00 2001 From: Florin Coras Date: Sun, 5 Mar 2023 11:45:38 -0800 Subject: [PATCH] vcl: always drain libc epoll with eventfds in ldp Otherwise if vcl epoll lt events are ignored by the app, libc and vcl mq events are never drained. Type: fix Signed-off-by: Florin Coras Change-Id: I1e22f6da46d56236c52714181f6c20dcb80a33a5 --- src/vcl/ldp.c | 53 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 17 deletions(-) diff --git a/src/vcl/ldp.c b/src/vcl/ldp.c index 9e01ac95bec..9876c1ea17a 100644 --- a/src/vcl/ldp.c +++ b/src/vcl/ldp.c @@ -2413,8 +2413,10 @@ epoll_ctl (int epfd, int op, int fd, struct epoll_event *event) * was acquired outside of the LD_PRELOAD process context. * In any case, if we get one, punt it to libc_epoll_ctl. */ - LDBG (1, "epfd %d: calling libc_epoll_ctl: op %d, fd %d" - " event %p", epfd, op, fd, event); + LDBG (1, + "epfd %d: calling libc_epoll_ctl: op %d, fd %d" + " events 0x%x", + epfd, op, fd, event ? event->events : 0); rv = libc_epoll_ctl (epfd, op, fd, event); goto done; @@ -2427,8 +2429,10 @@ epoll_ctl (int epfd, int op, int fd, struct epoll_event *event) if (vlsh != VLS_INVALID_HANDLE) { - LDBG (1, "epfd %d: calling vls_epoll_ctl: ep_vlsh %d op %d, vlsh %u," - " event %p", epfd, vep_vlsh, op, vlsh, event); + LDBG (1, + "epfd %d: calling vls_epoll_ctl: ep_vlsh %d op %d, vlsh %u," + " events 0x%x", + epfd, vep_vlsh, op, vlsh, event ? event->events : 0); rv = vls_epoll_ctl (vep_vlsh, op, vlsh, event); if (rv != VPPCOM_OK) @@ -2566,8 +2570,9 @@ static inline int ldp_epoll_pwait_eventfd (int epfd, struct epoll_event *events, int maxevents, int timeout, const sigset_t * sigmask) { + int libc_epfd, rv = 0, num_ev, libc_num_ev, vcl_wups = 0; + struct epoll_event *libc_evts; ldp_worker_ctx_t *ldpw; - int libc_epfd, rv = 0, num_ev, vcl_wups = 0; vls_handle_t ep_vlsh; ldp_init_check (); @@ -2643,7 +2648,11 @@ ldp_epoll_pwait_eventfd (int epfd, struct epoll_event *events, /* Request to only drain unhandled to prevent libc_epoll_wait starved */ rv = vls_epoll_wait (ep_vlsh, events, maxevents, -2); if (rv > 0) - goto done; + { + timeout = 0; + if (rv >= maxevents) + goto done; + } else if (PREDICT_FALSE (rv < 0)) { errno = -rv; @@ -2652,30 +2661,40 @@ ldp_epoll_pwait_eventfd (int epfd, struct epoll_event *events, } epoll_again: - rv = libc_epoll_pwait (libc_epfd, events, maxevents, timeout, sigmask); - if (rv <= 0) - goto done; - for (int i = 0; i < rv; i++) + + libc_evts = &events[rv]; + libc_num_ev = + libc_epoll_pwait (libc_epfd, libc_evts, maxevents - rv, timeout, sigmask); + if (libc_num_ev <= 0) + { + rv = rv >= 0 ? rv : -1; + goto done; + } + + for (int i = 0; i < libc_num_ev; i++) { - if (events[i].data.fd == ldpw->vcl_mq_epfd) + if (libc_evts[i].data.fd == ldpw->vcl_mq_epfd) { /* We should remove mq epoll fd from events. */ - rv--; - if (i != rv) + libc_num_ev--; + if (i != libc_num_ev) { - events[i].events = events[rv].events; - events[i].data.u64 = events[rv].data.u64; + libc_evts[i].events = libc_evts[libc_num_ev].events; + libc_evts[i].data.u64 = libc_evts[libc_num_ev].data.u64; } - num_ev = vls_epoll_wait (ep_vlsh, &events[rv], maxevents - rv, 0); + num_ev = vls_epoll_wait (ep_vlsh, &libc_evts[libc_num_ev], + maxevents - libc_num_ev, 0); if (PREDICT_TRUE (num_ev > 0)) rv += num_ev; /* Woken up by vcl but no events generated. Accept it once */ - if (rv == 0 && vcl_wups++ < 1) + if (rv == 0 && libc_num_ev == 0 && timeout && vcl_wups++ < 1) goto epoll_again; break; } } + rv += libc_num_ev; + done: return rv; } -- 2.16.6