Skip to content

Phantom event callbacks with EV_ET #984

@htuch

Description

@htuch

In Envoy today, we sometimes have network socket FDs setup with event_assign to watch for EV_CLOSED | EV_ET | EV_PERSIST. The callback function is invoked on EV_READ or EV_WRITE however, as a result of the following call chain:

  1. epoll_dispatch issuing read/write events with EV_ET set, see

    evmap_io_active_(base, events[i].data.fd, ev | EV_ET);
    .

  2. evmap_io_active masking out EV_READ and EV_WRITE (since we're only looking for EV_CLOSED) but preserving EV_ET in

    event_active_nolock_(ev, ev->ev_events & events, 1);
    .

  3. event_active_nolock_ delivering an event to the callback with res set to EV_ET, despite no registered event actually firing.

This can be fixed with the following patch:

diff --git a/evmap.c b/evmap.c
index ffc991f5..d824c062 100644
--- a/evmap.c
+++ b/evmap.c
@@ -432,7 +432,7 @@ evmap_io_active_(struct event_base *base, evutil_socket_t fd, short events)
        if (NULL == ctx)
                return;
        LIST_FOREACH(ev, &ctx->events, ev_io_next) {
-               if (ev->ev_events & events)
+               if (ev->ev_events & (events & (EV_READ | EV_WRITE | EV_CLOSED)))
                        event_active_nolock_(ev, ev->ev_events & events, 1);
        }
 }

I'm wondering if folks agree that this is a bug and whether the above patch is the correct fix?

CC @asraa @adisuissa

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions