mod_posix: Move everything to util.startup
This allows greater control over the order of events.
Notably, the internal ordering between daemonization, initialization of
libunbound and setup of signal handling is sensitive.
libunbound starts a separate thread for processing DNS requests.
If this thread is started before signal handling has been set up, it
will not inherit the signal handlers and instead behave as it would have
before signal handlers were set up, i.e. cause the whole process to
immediately exit.
libunbound is usually initialized on the first DNS request, usually
triggered by an outgoing s2s connection attempt.
If daemonization happens before signals have been set up, signals may
not be processed at all.
#!/usr/bin/env lua
-- Prosody IM
-- Copyright (C) 2008-2010 Matthew Wild
-- Copyright (C) 2008-2010 Waqas Hussain
--
-- This project is MIT/X11 licensed. Please see the
-- COPYING file in the source package for more information.
--
-- prosody - main executable for Prosody XMPP server
-- Will be modified by configure script if run --
CFG_SOURCEDIR=CFG_SOURCEDIR or os.getenv("PROSODY_SRCDIR");
CFG_CONFIGDIR=CFG_CONFIGDIR or os.getenv("PROSODY_CFGDIR");
CFG_PLUGINDIR=CFG_PLUGINDIR or os.getenv("PROSODY_PLUGINDIR");
CFG_DATADIR=CFG_DATADIR or os.getenv("PROSODY_DATADIR");
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
local function is_relative(path)
local path_sep = package.config:sub(1,1);
return ((path_sep == "/" and path:sub(1,1) ~= "/")
or (path_sep == "\\" and (path:sub(1,1) ~= "/" and path:sub(2,3) ~= ":\\")))
end
-- Tell Lua where to find our libraries
if CFG_SOURCEDIR then
local function filter_relative_paths(path)
if is_relative(path) then return ""; end
end
local function sanitise_paths(paths)
return (paths:gsub("[^;]+;?", filter_relative_paths):gsub(";;+", ";"));
end
package.path = sanitise_paths(CFG_SOURCEDIR.."/?.lua;"..package.path);
package.cpath = sanitise_paths(CFG_SOURCEDIR.."/?.so;"..package.cpath);
end
-- Substitute ~ with path to home directory in data path
if CFG_DATADIR then
if os.getenv("HOME") then
CFG_DATADIR = CFG_DATADIR:gsub("^~", os.getenv("HOME"));
end
end
-- Check before first require, to preempt the probable failure
if _VERSION < "Lua 5.2" then
io.stderr:write("Prosody is no longer compatible with Lua 5.1\n")
io.stderr:write("See https://prosody.im/doc/depends#lua for more information\n")
return os.exit(1);
end
if not pcall(require, "prosody.loader") then
pcall(require, "loader");
end
local startup = require "prosody.util.startup";
local async = require "prosody.util.async";
-- Note: it's important that this thread is not GC'd, as some C libraries
-- that are initialized here store a pointer to it ( :/ ).
local thread = async.runner();
thread:run(startup.prosody);
prosody.main_thread = thread;
local function loop()
-- Error handler for errors that make it this far
local function catch_uncaught_error(err)
if type(err) == "string" and err:match("interrupted!$") then
return "quitting";
end
prosody.log("error", "Top-level error, please report:\n%s", tostring(err));
local traceback = debug.traceback("", 2);
if traceback then
prosody.log("error", "%s", traceback);
end
prosody.events.fire_event("very-bad-error", {error = err, traceback = traceback});
end
local sleep = require"socket".sleep;
local server = require "prosody.net.server";
while select(2, xpcall(server.loop, catch_uncaught_error)) ~= "quitting" do
sleep(0.2);
end
end
loop();
startup.exit();