From 78be7279b0a003b262593a33cc7e40cf1ce62152 Mon Sep 17 00:00:00 2001 From: reverse Date: Wed, 19 Aug 2026 01:51:08 +0000 Subject: [PATCH] =?UTF-8?q?server:=20add=20a=20config=5Fgen=20counter=20bu?= =?UTF-8?q?mped=20on=20every=20rehash=20=E2=80=94=20lets=20modules=20cache?= =?UTF-8?q?=20config=20parsed=20into=20a=20hot-path=20structure=20and=20in?= =?UTF-8?q?validate=20it=20correctly=20(a=20REHASH=20can't=20leave=20a=20s?= =?UTF-8?q?tale=20cache),=20unblocking=20the=20per-message/per-command=20c?= =?UTF-8?q?onfig=20re-parse=20in=20disable/autodrop/securitygroups/restric?= =?UTF-8?q?tcommands/connclass?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/server.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/server.rs b/src/server.rs index 1f82967..220edcc 100644 --- a/src/server.rs +++ b/src/server.rs @@ -162,6 +162,10 @@ pub struct Server { /// settings via [`Server::conf`] / [`conf_all`] / [`conf_bool`] / [`conf_num`] /// — no per-module field lives on this struct (module-per-file rule). pub raw_config: HashMap>, + /// Bumped on every rehash. Modules that parse config into a hot-path structure + /// cache it in `ext` tagged with this value and re-parse only when it changes, + /// so a REHASH can never leave a stale cache (see e.g. `modules::disable`). + pub config_gen: u64, // labeled-response: while Some((uid, buf)), that client's own responses are // diverted into `buf` instead of the socket, so `on_line` can wrap them with // the command's `label` (single tag, BATCH, or ACK). RefCell because the @@ -217,6 +221,7 @@ impl Server { sasl_server: cfg.sasl_server, webirc: cfg.webirc, raw_config: cfg.raw, + config_gen: 0, label_capture: RefCell::new(None), log: RefCell::new(LogState::default()), event_tx, @@ -272,6 +277,7 @@ impl Server { self.sasl_server = fresh.sasl_server; self.webirc = fresh.webirc; self.raw_config = fresh.raw; + self.config_gen = self.config_gen.wrapping_add(1); // invalidate module config caches // Re-evaluate which linked servers are services against the fresh // `uline`/`sasl_server` config (re-evaluated on every rehash). let names: Vec<(String, String)> = self