plugins/mod_posix.lua
changeset 13465 c673ff1075bd
parent 13456 69faf3552d52
equal deleted inserted replaced
13464:a688947fab1e 13465: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);