From abac67299f00e20bf645f8c9bfcc3e28fa8cd99f Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Sat, 12 Dec 2020 21:53:28 +0000 Subject: [PATCH] Fix excessive CPU use on non-Linux systems when the open file limit is set high. Closes #1947. Thanks to Patrick TJ McPhee. --- ChangeLog.txt | 4 ++++ src/mux_poll.c | 30 +++++++++++++++++++++++++----- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/ChangeLog.txt b/ChangeLog.txt index 2923806f..817f99ec 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -1,3 +1,7 @@ +Broker: +- Fix excessive CPU use on non-Linux systems when the open file limit is set + high. Closes #1947. + Build: - Fix `install` target when using WITH_CJSON=no. Closes #1938. diff --git a/src/mux_poll.c b/src/mux_poll.c index 7f256916..79926641 100644 --- a/src/mux_poll.c +++ b/src/mux_poll.c @@ -59,15 +59,15 @@ Contributors: static void loop_handle_reads_writes(struct pollfd *pollfds); static struct pollfd *pollfds = NULL; -static size_t pollfd_max; +static size_t pollfd_max, pollfd_current_max; #ifndef WIN32 static sigset_t my_sigblock; #endif int mux_poll__init(struct mosquitto__listener_sock *listensock, int listensock_count) { - int i; - int pollfd_index = 0; + size_t i; + size_t pollfd_index = 0; #ifndef WIN32 sigemptyset(&my_sigblock); @@ -101,6 +101,7 @@ int mux_poll__init(struct mosquitto__listener_sock *listensock, int listensock_c pollfd_index++; } + pollfd_current_max = pollfd_index-1; return MOSQ_ERR_SUCCESS; } @@ -120,6 +121,9 @@ int mux_poll__add_out(struct mosquitto *context) pollfds[i].events = POLLIN | POLLOUT; pollfds[i].revents = 0; context->pollfd_index = i; + if(i > pollfd_current_max){ + pollfd_current_max = (size_t )i; + } break; } } @@ -150,6 +154,9 @@ int mux_poll__add_in(struct mosquitto *context) pollfds[i].events = POLLIN; pollfds[i].revents = 0; context->pollfd_index = i; + if(i > pollfd_current_max){ + pollfd_current_max = (size_t )i; + } break; } } @@ -160,11 +167,24 @@ int mux_poll__add_in(struct mosquitto *context) int mux_poll__delete(struct mosquitto *context) { + size_t pollfd_index; + if(context->pollfd_index != -1){ pollfds[context->pollfd_index].fd = INVALID_SOCKET; pollfds[context->pollfd_index].events = 0; pollfds[context->pollfd_index].revents = 0; + pollfd_index = (size_t )context->pollfd_index; context->pollfd_index = -1; + + /* If this is the highest index, reduce the current max until we find + * the next highest in use index. */ + while(pollfd_index == pollfd_current_max + && pollfd_index > 0 + && pollfds[pollfd_index].fd == INVALID_SOCKET){ + + pollfd_index--; + pollfd_current_max--; + } } return MOSQ_ERR_SUCCESS; @@ -184,10 +204,10 @@ int mux_poll__handle(struct mosquitto__listener_sock *listensock, int listensock #ifndef WIN32 sigprocmask(SIG_SETMASK, &my_sigblock, &origsig); - fdcount = poll(pollfds, pollfd_max, 100); + fdcount = poll(pollfds, pollfd_current_max+1, 100); sigprocmask(SIG_SETMASK, &origsig, NULL); #else - fdcount = WSAPoll(pollfds, pollfd_max, 100); + fdcount = WSAPoll(pollfds, pollfd_current_max+1, 100); #endif db.now_s = mosquitto_time();