view plugins/mod_debug_reset.lua @ 14181:6fb6e383123f 13.0

util.signal: Fix signalfd closure on non-Linux systems The loop was incorrect for 0-indexed arrays. It started at signalfd_num, which is the total number of signalfds, and decremented to 1 (condition was >0). So if 1 signalfd was registered, it would check only signalfds[1]. At capacity (32 signalfds) it would read past the end of the array. In every case, it would always skip the entry at position [0], leading to a leak. The swap-with-tail removal of the matched item used the post-decrement operator, leading to accessing the array slot just beyond the tail. Finally, it didn't break after finding a match. Probably harmless, but there isn't expected to be more than a single entry per fd, as far as I can tell.
author Matthew Wild <mwild1@gmail.com>
date Mon, 25 May 2026 16:02:39 +0100
parents 368df9b2d511
children
line wrap: on
line source

-- This module will "reset" the server when the client connection count drops
-- to zero. This is somewhere between a reload and a full process restart.
-- It is useful to ensure isolation between test runs, for example. It may
-- also be of use for some kinds of manual testing.

module:set_global();

local hostmanager = require "prosody.core.hostmanager";

local function do_reset()
	module:log("info", "Performing reset...");
	local hosts = {};
	for host in pairs(prosody.hosts) do
		table.insert(hosts, host);
	end
	module:fire_event("server-resetting");
	for _, host in ipairs(hosts) do
		hostmanager.deactivate(host);
		for _ = 1, 4 do
			-- Run a few cycles to ensure full cleanup, including
			-- weak tables and finalizers
			collectgarbage("collect");
		end
		hostmanager.activate(host);
		module:log("info", "Reset complete");
		module:fire_event("server-reset");
	end
end

function module.add_host(host_module)
	host_module:hook("resource-unbind", function ()
		if next(prosody.full_sessions) == nil then
			do_reset();
		end
	end);
end

local console_env = module:shared("/*/admin_shell/env");
console_env.debug_reset = {
	reset = do_reset;
};