From: liheng562653799 <47775671+liheng562653799@users.noreply.github.com> Date: Fri, 6 Aug 2021 04:00:56 +0000 (+0800) Subject: Update mini_event.c X-Git-Tag: release-1.14.0rc1~88^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=edbf9c21ee5c32f4ef52c2e3a16868fccc2d82e6;p=thirdparty%2Funbound.git Update mini_event.c When in heavy load, unbound opens many outside_network sockets for out going queries to delegation servers, which may result in a big fd(maxfd) value(for thread A 65500, for thread B 65501, for thread C ...). There are situations when thread A has a max fd num 65500 where maxfd is of course 65500, thread B has max fd num 20 for now but maxfd is still 65501. Though linux kernel checks whether maxfd+1 passed by select syscall is really the process' maxfd+1. Linux kernel can not tell maxfd+1 passed by thread B select syscall is much bigger(65501+1 or 65500+1 after trimed by kerne) than it should be (20+1). In this situation, when kernel do_select() for thread B, much work is wasted. --- diff --git a/util/mini_event.c b/util/mini_event.c index 661d88d2e..c05dc668c 100644 --- a/util/mini_event.c +++ b/util/mini_event.c @@ -337,6 +337,15 @@ int event_del(struct event* ev) FD_CLR(FD_SET_T ev->ev_fd, &ev->ev_base->writes); FD_CLR(FD_SET_T ev->ev_fd, &ev->ev_base->ready); FD_CLR(FD_SET_T ev->ev_fd, &ev->ev_base->content); + if(ev->ev_fd == ev->ev_base->maxfd) { + int i = ev->ev_base->maxfd - 1; + for (; i > 3; i--) { + if (NULL != ev->ev_base->fds[i]) { + break; + } + } + ev->ev_base->maxfd = i; + } } ev->added = 0; return 0;