From 59ea3c6753e80d051b20223cb327294cac985afe Mon Sep 17 00:00:00 2001 From: Ed Kellett Date: Sun, 5 Nov 2023 22:05:41 +0000 Subject: [PATCH] Delay rehashing until we're not processing events Fixes crash introduced by 0ab6dbbc651ddd1c26cb7baa6e6cf86890a4abd2. It's probably a regression since it defeats a system designed to stop this from happening, but I didn't dig through the history. rehash() closes listeners. If we happen to get a single epoll() result that wants to first rehash and then accept a connection, the epoll info will point to a freed rb_fde_t. Other selectors should have similar problems, but we didn't investigate that. rb_fde_ts are normally batched up and freed outside the event processing, but as of the above commit close_listeners() screws that up by closing pending FDs immediately in order to create new listeners. I think it might be a bit better to revert this behaviour and simply not close listeners if we are going to open new ones over them, but have opted for the smallest reasonable change I can think of. Helped-by: Eric Mertens --- ircd/s_conf.c | 35 ++++++++++++++++++++++++++--------- librb/include/rb_commio.h | 1 + librb/src/commio.c | 25 +++++++++++++++++++++++++ librb/src/export-syms.txt | 1 + 4 files changed, 53 insertions(+), 9 deletions(-) diff --git a/ircd/s_conf.c b/ircd/s_conf.c index cb86811f..4c6b9908 100644 --- a/ircd/s_conf.c +++ b/ircd/s_conf.c @@ -642,16 +642,18 @@ attach_conf(struct Client *client_p, struct ConfItem *aconf) return (0); } -/* - * rehash - * - * Actual REHASH service routine. Called with sig == 0 if it has been called - * as a result of an operator issuing this command, else assume it has been - * called as a result of the server receiving a HUP signal. - */ -bool -rehash(bool sig) +struct rehash_data { + bool sig; +}; + +static void +service_rehash(void *data_) { + struct rehash_data *data = data_; + bool sig = data->sig; + + free(data); + rb_dlink_node *n; hook_data_rehash hdata = { sig }; @@ -684,6 +686,21 @@ rehash(bool sig) privilegeset_cleanup_rehash(); call_hook(h_rehash, &hdata); +} + +/* + * rehash + * + * Called with sig == 0 if it has been called as a result of an operator + * issuing this command, else assume it has been called as a result of the + * server receiving a HUP signal. + */ +bool +rehash(bool sig) +{ + struct rehash_data *data = rb_malloc(sizeof *data); + data->sig = sig; + rb_defer(service_rehash, data); return false; } diff --git a/librb/include/rb_commio.h b/librb/include/rb_commio.h index dde5ca9c..79d88461 100644 --- a/librb/include/rb_commio.h +++ b/librb/include/rb_commio.h @@ -159,6 +159,7 @@ int rb_ignore_errno(int); void rb_setselect(rb_fde_t *, unsigned int type, PF * handler, void *client_data); void rb_init_netio(void); int rb_select(unsigned long); +void rb_defer(void (*)(void *), void *); int rb_fd_ssl(rb_fde_t *F); int rb_get_fd(rb_fde_t *F); const char *rb_get_ssl_strerror(rb_fde_t *F); diff --git a/librb/src/commio.c b/librb/src/commio.c index 490706f9..47a042c5 100644 --- a/librb/src/commio.c +++ b/librb/src/commio.c @@ -51,6 +51,14 @@ static rb_bh *fd_heap; static rb_dlink_list timeout_list; static rb_dlink_list closed_list; +struct defer +{ + rb_dlink_node node; + void (*fn)(void *); + void *data; +}; +static rb_dlink_list defer_list; + static struct ev_entry *rb_timeout_ev; @@ -2015,10 +2023,27 @@ rb_setselect(rb_fde_t *F, unsigned int type, PF * handler, void *client_data) setselect_handler(F, type, handler, client_data); } +void +rb_defer(void (*fn)(void *), void *data) +{ + struct defer *defer = rb_malloc(sizeof *defer); + defer->fn = fn; + defer->data = data; + rb_dlinkAdd(defer, &defer->node, &defer_list); +} + int rb_select(unsigned long timeout) { int ret = select_handler(timeout); + rb_dlink_node *ptr, *next; + RB_DLINK_FOREACH_SAFE(ptr, next, defer_list.head) + { + struct defer *defer = ptr->data; + defer->fn(defer->data); + rb_dlinkDelete(ptr, &defer_list); + rb_free(defer); + } rb_close_pending_fds(); return ret; } diff --git a/librb/src/export-syms.txt b/librb/src/export-syms.txt index e6ec7af5..6d9a0b89 100644 --- a/librb/src/export-syms.txt +++ b/librb/src/export-syms.txt @@ -27,6 +27,7 @@ rb_ctime rb_current_time rb_current_time_tv rb_date +rb_defer rb_destroy_patricia rb_dictionary_add rb_dictionary_create