Improved epoll failures handling.

epoll changes are committed to the kernel before epoll_wait() or
on changes array overflow.  In the latter case if there are errors
epoll_wait() timeout was not set to zero.

This commit is related to #173 issue on GitHub.
Thanks to 洪志道 (Hong Zhi Dao).
This commit is contained in:
Igor Sysoev
2018-10-22 17:43:28 +03:00
parent deeb276d23
commit 50dd54877d
2 changed files with 13 additions and 12 deletions

View File

@@ -67,7 +67,7 @@ static void nxt_epoll_enable_accept(nxt_event_engine_t *engine,
nxt_fd_event_t *ev);
static void nxt_epoll_change(nxt_event_engine_t *engine, nxt_fd_event_t *ev,
int op, uint32_t events);
static nxt_int_t nxt_epoll_commit_changes(nxt_event_engine_t *engine);
static void nxt_epoll_commit_changes(nxt_event_engine_t *engine);
static void nxt_epoll_error_handler(nxt_task_t *task, void *obj, void *data);
#if (NXT_HAVE_SIGNALFD)
static nxt_int_t nxt_epoll_add_signal(nxt_event_engine_t *engine);
@@ -593,7 +593,7 @@ nxt_epoll_change(nxt_event_engine_t *engine, nxt_fd_event_t *ev, int op,
engine->u.epoll.fd, ev->fd, op, events);
if (engine->u.epoll.nchanges >= engine->u.epoll.mchanges) {
(void) nxt_epoll_commit_changes(engine);
nxt_epoll_commit_changes(engine);
}
ev->changing = 1;
@@ -605,18 +605,16 @@ nxt_epoll_change(nxt_event_engine_t *engine, nxt_fd_event_t *ev, int op,
}
static nxt_int_t
static void
nxt_epoll_commit_changes(nxt_event_engine_t *engine)
{
int ret;
nxt_int_t retval;
nxt_fd_event_t *ev;
nxt_epoll_change_t *change, *end;
nxt_debug(&engine->task, "epoll %d changes:%ui",
engine->u.epoll.fd, engine->u.epoll.nchanges);
retval = NXT_OK;
change = engine->u.epoll.changes;
end = change + engine->u.epoll.nchanges;
@@ -637,7 +635,7 @@ nxt_epoll_commit_changes(nxt_event_engine_t *engine)
nxt_work_queue_add(&engine->fast_work_queue,
nxt_epoll_error_handler, ev->task, ev, ev->data);
retval = NXT_ERROR;
engine->u.epoll.error = 1;
}
change++;
@@ -645,8 +643,6 @@ nxt_epoll_commit_changes(nxt_event_engine_t *engine)
} while (change < end);
engine->u.epoll.nchanges = 0;
return retval;
}
@@ -884,10 +880,13 @@ nxt_epoll_poll(nxt_event_engine_t *engine, nxt_msec_t timeout)
struct epoll_event *event;
if (engine->u.epoll.nchanges != 0) {
if (nxt_epoll_commit_changes(engine) != NXT_OK) {
/* Error handlers have been enqueued on failure. */
timeout = 0;
}
nxt_epoll_commit_changes(engine);
}
if (engine->u.epoll.error) {
engine->u.epoll.error = 0;
/* Error handlers have been enqueued on failure. */
timeout = 0;
}
nxt_debug(&engine->task, "epoll_wait(%d) timeout:%M",

View File

@@ -202,6 +202,8 @@ typedef struct {
nxt_uint_t mchanges;
int mevents;
uint8_t error; /* 1 bit */
nxt_epoll_change_t *changes;
struct epoll_event *events;