From f6a58b60af9220fa23e7361328f99c7902e2fc06 Mon Sep 17 00:00:00 2001 From: Bram Matthys Date: Wed, 9 Dec 2015 17:44:54 +0100 Subject: [PATCH] Added workaround for "Cannot accept connections: Operation not supported" problem (#4469). --- include/h.h | 1 + src/s_bsd.c | 25 +++++++++++++++++++------ src/s_conf.c | 12 +++++++----- 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/include/h.h b/include/h.h index e11d45187..b4e1386b5 100644 --- a/include/h.h +++ b/include/h.h @@ -754,3 +754,4 @@ extern MODVAR aClient *remote_rehash_client; extern MODVAR int debugfd; extern void convert_to_absolute_path(char **path, char *reldir); extern int has_channel_mode(aChannel *chptr, char mode); +extern void start_listeners(void); diff --git a/src/s_bsd.c b/src/s_bsd.c index 04972ae4d..35cf1ac25 100644 --- a/src/s_bsd.c +++ b/src/s_bsd.c @@ -95,6 +95,7 @@ void completed_connection(int, int, void *); static int check_init(aClient *, char *, size_t); void set_sock_opts(int, aClient *, int); void set_ipv6_opts(int); +void close_listener(ConfigItem_listen *listener); static char readbuf[BUFSIZE]; char zlinebuf[BUFSIZE]; extern char *version; @@ -285,19 +286,31 @@ void report_baderror(char *text, aClient *cptr) /** Accept an incoming client. */ static void listener_accept(int listener_fd, int revents, void *data) { - ConfigItem_listen *cptr = data; + ConfigItem_listen *listener = data; int cli_fd; - if ((cli_fd = fd_accept(cptr->fd)) < 0) + if ((cli_fd = fd_accept(listener->fd)) < 0) { - if ((ERRNO != P_EWOULDBLOCK) && (ERRNO != P_ECONNABORTED)) + if ((ERRNO != P_EWOULDBLOCK) && (ERRNO != P_ECONNABORTED)) + { + /* Trouble! accept() returns a strange error. + * Previously in such a case we would just log/broadcast the error and return, + * causing this message to be triggered at a rate of XYZ per second (100% CPU). + * Now we close & re-start the listener. + * Of course the underlying cause of this issue should be investigated, as this + * is very much a workaround. + */ report_baderror("Cannot accept connections %s:%s", NULL); + sendto_realops("[BUG] Restarting listener on %s:%d due to fatal errors (see previous message)", listener->ip, listener->port); + close_listener(listener); + start_listeners(); + } return; } ircstp->is_ac++; - set_sock_opts(cli_fd, NULL, cptr->ipv6); + set_sock_opts(cli_fd, NULL, listener->ipv6); set_non_blocking(cli_fd, NULL); if ((++OpenFiles >= MAXCLIENTS) || (cli_fd >= MAXCLIENTS)) @@ -305,7 +318,7 @@ static void listener_accept(int listener_fd, int revents, void *data) ircstp->is_ref++; if (last_allinuse < TStime() - 15) { - sendto_realops("All connections in use. ([@%s/%u])", cptr->ip, cptr->port); + sendto_realops("All connections in use. ([@%s/%u])", listener->ip, listener->port); last_allinuse = TStime(); } @@ -317,7 +330,7 @@ static void listener_accept(int listener_fd, int revents, void *data) } /* add_connection() may fail. we just don't care. */ - (void)add_connection(cptr, cli_fd); + (void)add_connection(listener, cli_fd); } /* diff --git a/src/s_conf.c b/src/s_conf.c index 7547e6dbf..cd10db150 100644 --- a/src/s_conf.c +++ b/src/s_conf.c @@ -8087,11 +8087,7 @@ int _test_loadmodule(ConfigFile *conf, ConfigEntry *ce) return 0; } -/* - * Actually use configuration -*/ - -void run_configuration(void) +void start_listeners(void) { ConfigItem_listen *listenptr; int failed = 0, ports_bound = 0; @@ -8164,6 +8160,12 @@ void run_configuration(void) } } +/* Actually use configuration */ +void run_configuration(void) +{ + start_listeners(); +} + int _conf_offchans(ConfigFile *conf, ConfigEntry *ce) { ConfigEntry *cep, *cepp;