From 4c13afaeec2d35df2580dfbc49391d0524101248 Mon Sep 17 00:00:00 2001 From: Azat Khuzhin Date: Tue, 5 May 2020 01:13:49 +0300 Subject: [PATCH] Support EV_CLOSED on linux for poll(2) Refs: #984 --- poll.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/poll.c b/poll.c index fe440711..ddae2bf0 100644 --- a/poll.c +++ b/poll.c @@ -53,6 +53,17 @@ #include "evthread-internal.h" #include "time-internal.h" +/* Since Linux 2.6.17, poll is able to report about peer half-closed connection + using special POLLRDHUP flag on a read event. +*/ +#if !defined(POLLRDHUP) +#define POLLRDHUP 0 +#define EARLY_CLOSE_IF_HAVE_RDHUP 0 +#else +#define EARLY_CLOSE_IF_HAVE_RDHUP EV_FEATURE_EARLY_CLOSE +#endif + + struct pollidx { int idxplus1; }; @@ -80,7 +91,7 @@ const struct eventop pollops = { poll_dispatch, poll_dealloc, 0, /* doesn't need_reinit */ - EV_FEATURE_FDS, + EV_FEATURE_FDS|EARLY_CLOSE_IF_HAVE_RDHUP, sizeof(struct pollidx), }; @@ -204,6 +215,8 @@ poll_dispatch(struct event_base *base, struct timeval *tv) res |= EV_READ; if (what & POLLOUT) res |= EV_WRITE; + if (what & POLLRDHUP) + res |= EV_CLOSED; if (res == 0) continue; @@ -222,7 +235,7 @@ poll_add(struct event_base *base, int fd, short old, short events, void *idx_) int i; EVUTIL_ASSERT((events & EV_SIGNAL) == 0); - if (!(events & (EV_READ|EV_WRITE))) + if (!(events & (EV_READ|EV_WRITE|EV_CLOSED))) return (0); poll_check_ok(pop); @@ -265,6 +278,8 @@ poll_add(struct event_base *base, int fd, short old, short events, void *idx_) pfd->events |= POLLOUT; if (events & EV_READ) pfd->events |= POLLIN; + if (events & EV_CLOSED) + pfd->events |= POLLRDHUP; poll_check_ok(pop); return (0); @@ -283,7 +298,7 @@ poll_del(struct event_base *base, int fd, short old, short events, void *idx_) int i; EVUTIL_ASSERT((events & EV_SIGNAL) == 0); - if (!(events & (EV_READ|EV_WRITE))) + if (!(events & (EV_READ|EV_WRITE|EV_CLOSED))) return (0); poll_check_ok(pop); @@ -297,6 +312,8 @@ poll_del(struct event_base *base, int fd, short old, short events, void *idx_) pfd->events &= ~POLLIN; if (events & EV_WRITE) pfd->events &= ~POLLOUT; + if (events & EV_CLOSED) + pfd->events &= ~POLLRDHUP; poll_check_ok(pop); if (pfd->events) /* Another event cares about that fd. */ -- 2.50.1