2 -- Copyright (C) 2008-2010 Matthew Wild
3 -- Copyright (C) 2008-2010 Waqas Hussain
5 -- This project is MIT/X11 licensed. Please see the
6 -- COPYING file in the source package for more information.
10 local want_pposix_version
= "0.4.0";
12 local pposix
= assert(require
"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
);
18 local have_signal
, signal
= pcall(require
, "util.signal");
19 if not have_signal
then
20 module
:log("warn", "Couldn't load signal library, won't respond to SIGTERM");
23 local format = require
"util.format".format;
24 local lfs
= require
"lfs";
25 local stat
= lfs
.attributes
;
27 local prosody
= _G
.prosody
;
29 module
:set_global(); -- we're a global module
31 local umask
= module
:get_option_string("umask", "027");
34 -- Allow switching away from root, some people like strange ports.
35 module
:hook("server-started", function ()
36 local uid
= module
:get_option("setuid");
37 local gid
= module
:get_option("setgid");
39 local success
, msg
= pposix
.setgid(gid
);
41 module
:log("debug", "Changed group to %s successfully.", gid
);
43 module
:log("error", "Failed to change group to %s. Error: %s", gid
, msg
);
44 prosody
.shutdown("Failed to change group to %s", gid
);
48 local success
, msg
= pposix
.setuid(uid
);
50 module
:log("debug", "Changed user to %s successfully.", uid
);
52 module
:log("error", "Failed to change user to %s. Error: %s", uid
, msg
);
53 prosody
.shutdown("Failed to change user to %s", uid
);
58 -- Don't even think about it!
59 if not prosody
.start_time
then -- server-starting
60 local suid
= module
:get_option("setuid");
61 if not suid
or suid
== 0 or suid
== "root" then
62 if pposix
.getuid() == 0 and not module
:get_option_boolean("run_as_root") then
63 module
:log("error", "Danger, Will Robinson! Prosody doesn't need to be run as root, so don't do it!");
64 module
:log("error", "For more information on running Prosody as root, see https://prosody.im/doc/root");
65 prosody
.shutdown("Refusing to run as root");
73 local function remove_pidfile()
74 if pidfile_handle
then
75 pidfile_handle
:close();
77 pidfile
, pidfile_handle
= nil, nil;
81 local function write_pidfile()
82 if pidfile_handle
then
85 pidfile
= module
:get_option_path("pidfile", nil, "data");
88 local mode
= stat(pidfile
) and "r+" or "w+";
89 pidfile_handle
, err
= io
.open(pidfile
, mode
);
90 if not pidfile_handle
then
91 module
:log("error", "Couldn't write pidfile at %s; %s", pidfile
, err
);
92 prosody
.shutdown("Couldn't write pidfile");
94 if not lfs
.lock(pidfile_handle
, "w") then -- Exclusive lock
95 local other_pid
= pidfile_handle
:read("*a");
96 module
:log("error", "Another Prosody instance seems to be running with PID %s, quitting", other_pid
);
98 prosody
.shutdown("Prosody already running");
100 pidfile_handle
:close();
101 pidfile_handle
, err
= io
.open(pidfile
, "w+");
102 if not pidfile_handle
then
103 module
:log("error", "Couldn't write pidfile at %s; %s", pidfile
, err
);
104 prosody
.shutdown("Couldn't write pidfile");
106 if lfs
.lock(pidfile_handle
, "w") then
107 pidfile_handle
:write(tostring(pposix
.getpid()));
108 pidfile_handle
:flush();
117 function syslog_sink_maker(config
) -- luacheck: ignore 212/config
118 if not syslog_opened
then
119 pposix
.syslog_open("prosody", module
:get_option_string("syslog_facility"));
120 syslog_opened
= true;
122 local syslog
= pposix
.syslog_log
;
123 return function (name
, level
, message
, ...)
124 syslog(level
, name
, format(message
, ...));
127 require
"core.loggingmanager".register_sink_type("syslog", syslog_sink_maker
);
129 local daemonize
= module
:get_option("daemonize", prosody
.installed
);
131 local function remove_log_sinks()
132 local lm
= require
"core.loggingmanager";
133 lm
.register_sink_type("console", nil);
134 lm
.register_sink_type("stdout", nil);
139 local function daemonize_server()
140 module
:log("info", "Prosody is about to detach from the console, disabling further console output");
142 local ok
, ret
= pposix
.daemonize();
144 module
:log("error", "Failed to daemonize: %s", ret
);
145 elseif ret
and ret
> 0 then
148 module
:log("info", "Successfully daemonized to PID %d", pposix
.getpid());
152 if not prosody
.start_time
then -- server-starting
156 -- Not going to daemonize, so write the pid of this process
160 module
:hook("server-stopped", remove_pidfile
);
162 -- Set signal handlers
164 module
:add_timer(0, function ()
165 signal
.signal("SIGTERM", function ()
166 module
:log("warn", "Received SIGTERM");
167 prosody
.unlock_globals();
168 prosody
.shutdown("Received SIGTERM");
169 prosody
.lock_globals();
172 signal
.signal("SIGHUP", function ()
173 module
:log("info", "Received SIGHUP");
174 prosody
.reload_config();
175 -- this also reloads logging
178 signal
.signal("SIGINT", function ()
179 module
:log("info", "Received SIGINT");
180 prosody
.unlock_globals();
181 prosody
.shutdown("Received SIGINT");
182 prosody
.lock_globals();