]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
Update mini_event.c 521/head
authorliheng562653799 <47775671+liheng562653799@users.noreply.github.com>
Fri, 6 Aug 2021 04:00:56 +0000 (12:00 +0800)
committerGitHub <noreply@github.com>
Fri, 6 Aug 2021 04:00:56 +0000 (12:00 +0800)
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.

util/mini_event.c

index 661d88d2e6f60faace77e909318ccd69df91a5e6..c05dc668c676ccde8a8a7cadf46c95d02263bd7c 100644 (file)
@@ -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;