diff --git a/src/knot/server/tcp-handler.c b/src/knot/server/tcp-handler.c index 1f18abfdf8ab5ad1220b4d56a47533d928f5fe8d..5b6ac941f0ed7e27eddb76fd0fd2d2d0ce94d286 100644 --- a/src/knot/server/tcp-handler.c +++ b/src/knot/server/tcp-handler.c @@ -543,7 +543,16 @@ int tcp_loop_master(dthread_t *thread) } for (unsigned i = 0; nfds > 0 && i < set.n; ++i) { - /* Skip inactive. */ + + /* Error events. */ + if (set.pfd[i].revents & (POLLERR|POLLHUP|POLLNVAL)) { + socket_close(set.pfd[i].fd); + fdset_remove(&set, i); + --nfds; /* Treat error event as activity. */ + continue; /* Stay on the same index. */ + } + + /* Accept POLLIN events. */ if (!(set.pfd[i].revents & POLLIN)) continue; @@ -611,6 +620,15 @@ int tcp_loop_worker(dthread_t *thread) unsigned i = 0; while (nfds > 0 && i < set->n) { + /* Terminate faulty connections. */ + int fd = set->pfd[i].fd; + if (set->pfd[i].revents & (POLLERR|POLLHUP|POLLNVAL)) { + fdset_remove(set, i); + close(fd); + --nfds; /* Treat error event as activity. */ + continue; /* Stay on the same index. */ + } + if (!(set->pfd[i].revents & set->pfd[i].events)) { /* Skip inactive. */ ++i; @@ -621,7 +639,6 @@ int tcp_loop_worker(dthread_t *thread) } /* Register new TCP client or process a query. */ - int fd = set->pfd[i].fd; if (fd == w->pipe[0]) { tcp_loop_assign(fd, set); } else { diff --git a/src/knot/server/xfr-handler.c b/src/knot/server/xfr-handler.c index 90b0a42ecab65c8dc9632aebc454aa290f011ef0..a99b5d342914ab93305d40969fccc8ddeda01580 100644 --- a/src/knot/server/xfr-handler.c +++ b/src/knot/server/xfr-handler.c @@ -1101,21 +1101,19 @@ int xfr_worker(dthread_t *thread) unsigned i = 0; while (nfds > 0 && i < set.n && !dt_is_cancelled(thread)) { - if (!(set.pfd[i].revents & set.pfd[i].events)) { - /* Skip inactive. */ - ++i; - continue; - } else { + knot_ns_xfr_t *rq = (knot_ns_xfr_t *)set.ctx[i]; + if (set.pfd[i].revents & (POLLERR|POLLHUP|POLLNVAL)) { + /* Error events. */ + --nfds; /* Treat error event as activity. */ + ret = KNOT_ECONN; /* Force disconnect */ + } else if (set.pfd[i].revents & set.pfd[i].events) { /* One less active event. */ --nfds; - } - - /* Process pending tasks. */ - knot_ns_xfr_t *rq = (knot_ns_xfr_t *)set.ctx[i]; - if (rq->flags & XFR_FLAG_CONNECTING) { - ret = xfr_async_finish(&set, i); - } else { - ret = xfr_process_event(w, rq); + /* Process pending tasks. */ + if (rq->flags & XFR_FLAG_CONNECTING) + ret = xfr_async_finish(&set, i); + else + ret = xfr_process_event(w, rq); } /* Check task state. */