Software /
code /
prosody
Comparison
plugins/mod_posix.lua @ 13461:c673ff1075bd
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.
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Sat, 23 Mar 2024 20:48:19 +0100 |
parent | 13452:69faf3552d52 |
comparison
equal
deleted
inserted
replaced
13460:a688947fab1e | 13461:c673ff1075bd |
---|---|
4 -- | 4 -- |
5 -- This project is MIT/X11 licensed. Please see the | 5 -- This project is MIT/X11 licensed. Please see the |
6 -- COPYING file in the source package for more information. | 6 -- COPYING file in the source package for more information. |
7 -- | 7 -- |
8 | 8 |
9 | |
10 local want_pposix_version = "0.4.0"; | |
11 | |
12 local pposix = assert(require "prosody.util.pposix"); | |
13 if pposix._VERSION ~= want_pposix_version then | |
14 module:log("warn", "Unknown version (%s) of binary pposix module, expected %s." | |
15 .. "Perhaps you need to recompile?", tostring(pposix._VERSION), want_pposix_version); | |
16 end | |
17 | |
18 | |
19 local lfs = require "lfs"; | |
20 local stat = lfs.attributes; | |
21 | |
22 local prosody = _G.prosody; | |
23 | |
24 module:set_global(); -- we're a global module | 9 module:set_global(); -- we're a global module |
25 | 10 |
26 local umask = module:get_option_string("umask", "027"); | 11 -- TODO delete this whole concept |
27 pposix.umask(umask); | |
28 | |
29 -- Don't even think about it! | |
30 if not prosody.start_time then -- server-starting | |
31 if pposix.getuid() == 0 and not module:get_option_boolean("run_as_root") then | |
32 module:log("error", "Danger, Will Robinson! Prosody doesn't need to be run as root, so don't do it!"); | |
33 module:log("error", "For more information on running Prosody as root, see https://prosody.im/doc/root"); | |
34 prosody.shutdown("Refusing to run as root", 1); | |
35 end | |
36 end | |
37 | |
38 local pidfile; | |
39 local pidfile_handle; | |
40 | |
41 local function remove_pidfile() | |
42 if pidfile_handle then | |
43 pidfile_handle:close(); | |
44 os.remove(pidfile); | |
45 pidfile, pidfile_handle = nil, nil; | |
46 end | |
47 end | |
48 | |
49 local function write_pidfile() | |
50 if pidfile_handle then | |
51 remove_pidfile(); | |
52 end | |
53 pidfile = module:get_option_path("pidfile", nil, "data"); | |
54 if pidfile then | |
55 local err; | |
56 local mode = stat(pidfile) and "r+" or "w+"; | |
57 pidfile_handle, err = io.open(pidfile, mode); | |
58 if not pidfile_handle then | |
59 module:log("error", "Couldn't write pidfile at %s; %s", pidfile, err); | |
60 prosody.shutdown("Couldn't write pidfile", 1); | |
61 else | |
62 if not lfs.lock(pidfile_handle, "w") then -- Exclusive lock | |
63 local other_pid = pidfile_handle:read("*a"); | |
64 module:log("error", "Another Prosody instance seems to be running with PID %s, quitting", other_pid); | |
65 pidfile_handle = nil; | |
66 prosody.shutdown("Prosody already running", 1); | |
67 else | |
68 pidfile_handle:close(); | |
69 pidfile_handle, err = io.open(pidfile, "w+"); | |
70 if not pidfile_handle then | |
71 module:log("error", "Couldn't write pidfile at %s; %s", pidfile, err); | |
72 prosody.shutdown("Couldn't write pidfile", 1); | |
73 else | |
74 if lfs.lock(pidfile_handle, "w") then | |
75 pidfile_handle:write(tostring(pposix.getpid())); | |
76 pidfile_handle:flush(); | |
77 end | |
78 end | |
79 end | |
80 end | |
81 end | |
82 end | |
83 | |
84 local daemonize = prosody.opts.daemonize; | |
85 | |
86 if daemonize == nil then | |
87 -- Fall back to config file if not specified on command-line | |
88 daemonize = module:get_option_boolean("daemonize", nil); | |
89 if daemonize ~= nil then | |
90 module:log("warn", "The 'daemonize' option has been deprecated, specify -D or -F on the command line instead."); | |
91 -- TODO: Write some docs and include a link in the warning. | |
92 end | |
93 end | |
94 | |
95 local function remove_log_sinks() | |
96 local lm = require "prosody.core.loggingmanager"; | |
97 lm.register_sink_type("console", nil); | |
98 lm.register_sink_type("stdout", nil); | |
99 lm.reload_logging(); | |
100 end | |
101 | |
102 if daemonize then | |
103 local function daemonize_server() | |
104 module:log("info", "Prosody is about to detach from the console, disabling further console output"); | |
105 remove_log_sinks(); | |
106 local ok, ret = pposix.daemonize(); | |
107 if not ok then | |
108 module:log("error", "Failed to daemonize: %s", ret); | |
109 elseif ret and ret > 0 then | |
110 os.exit(0); | |
111 else | |
112 module:log("info", "Successfully daemonized to PID %d", pposix.getpid()); | |
113 write_pidfile(); | |
114 end | |
115 end | |
116 module:hook("server-started", daemonize_server) | |
117 else | |
118 -- Not going to daemonize, so write the pid of this process | |
119 write_pidfile(); | |
120 end | |
121 | |
122 module:hook("server-stopped", remove_pidfile); |