From 299ff2b23ffbd3c4511768f7bfbf427315b0650d Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Fri, 24 Jan 2014 16:12:10 +0100 Subject: move daemonization code to unix/ --- Makefile.am | 6 +- src/Daemon.cxx | 268 -------------------------------------------- src/Daemon.hxx | 99 ---------------- src/Main.cxx | 4 +- src/PidFile.hxx | 85 -------------- src/SignalHandlers.cxx | 82 -------------- src/SignalHandlers.hxx | 31 ----- src/unix/Daemon.cxx | 268 ++++++++++++++++++++++++++++++++++++++++++++ src/unix/Daemon.hxx | 99 ++++++++++++++++ src/unix/PidFile.hxx | 85 ++++++++++++++ src/unix/SignalHandlers.cxx | 82 ++++++++++++++ src/unix/SignalHandlers.hxx | 31 +++++ 12 files changed, 570 insertions(+), 570 deletions(-) delete mode 100644 src/Daemon.cxx delete mode 100644 src/Daemon.hxx delete mode 100644 src/PidFile.hxx delete mode 100644 src/SignalHandlers.cxx delete mode 100644 src/SignalHandlers.hxx create mode 100644 src/unix/Daemon.cxx create mode 100644 src/unix/Daemon.hxx create mode 100644 src/unix/PidFile.hxx create mode 100644 src/unix/SignalHandlers.cxx create mode 100644 src/unix/SignalHandlers.hxx diff --git a/Makefile.am b/Makefile.am index cd2c4c555..debdbab40 100644 --- a/Makefile.am +++ b/Makefile.am @@ -157,8 +157,9 @@ src_mpd_SOURCES = \ src/Instance.cxx src/Instance.hxx \ src/Win32Main.cxx \ src/GlobalEvents.cxx src/GlobalEvents.hxx \ - src/Daemon.cxx src/Daemon.hxx \ - src/PidFile.hxx \ + src/unix/SignalHandlers.cxx src/unix/SignalHandlers.hxx \ + src/unix/Daemon.cxx src/unix/Daemon.hxx \ + src/unix/PidFile.hxx \ src/AudioCompress/compress.c \ src/MixRampInfo.hxx \ src/MusicBuffer.cxx src/MusicBuffer.hxx \ @@ -194,7 +195,6 @@ src_mpd_SOURCES = \ src/queue/QueueSave.cxx src/queue/QueueSave.hxx \ src/ReplayGainConfig.cxx src/ReplayGainConfig.hxx \ src/ReplayGainInfo.cxx src/ReplayGainInfo.hxx \ - src/SignalHandlers.cxx src/SignalHandlers.hxx \ src/DetachedSong.cxx src/DetachedSong.hxx \ src/LightSong.cxx src/LightSong.hxx \ src/LightDirectory.hxx \ diff --git a/src/Daemon.cxx b/src/Daemon.cxx deleted file mode 100644 index 490b2def5..000000000 --- a/src/Daemon.cxx +++ /dev/null @@ -1,268 +0,0 @@ -/* - * Copyright (C) 2003-2014 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "config.h" -#include "Daemon.hxx" -#include "system/FatalError.hxx" -#include "fs/AllocatedPath.hxx" -#include "fs/FileSystem.hxx" -#include "util/Domain.hxx" -#include "PidFile.hxx" -#include "Log.hxx" - -#include -#include -#include - -#ifndef WIN32 -#include -#include -#include -#include -#endif - -static constexpr Domain daemon_domain("daemon"); - -#ifndef WIN32 - -/** the Unix user name which MPD runs as */ -static char *user_name; - -/** the Unix user id which MPD runs as */ -static uid_t user_uid = (uid_t)-1; - -/** the Unix group id which MPD runs as */ -static gid_t user_gid = (gid_t)-1; - -/** the absolute path of the pidfile */ -static AllocatedPath pidfile = AllocatedPath::Null(); - -/* whether "group" conf. option was given */ -static bool had_group = false; - -/** - * The write end of a pipe that is used to notify the parent process - * that initialization has finished and that it should detach. - */ -static int detach_fd = -1; - -void -daemonize_kill(void) -{ - FILE *fp; - int pid, ret; - - if (pidfile.IsNull()) - FatalError("no pid_file specified in the config file"); - - fp = FOpen(pidfile, "r"); - if (fp == nullptr) { - const std::string utf8 = pidfile.ToUTF8(); - FormatFatalSystemError("Unable to open pid file \"%s\"", - utf8.c_str()); - } - - if (fscanf(fp, "%i", &pid) != 1) { - const std::string utf8 = pidfile.ToUTF8(); - FormatFatalError("unable to read the pid from file \"%s\"", - utf8.c_str()); - } - fclose(fp); - - ret = kill(pid, SIGTERM); - if (ret < 0) - FormatFatalSystemError("unable to kill process %i", - int(pid)); - - exit(EXIT_SUCCESS); -} - -void -daemonize_close_stdin(void) -{ - close(STDIN_FILENO); - open("/dev/null", O_RDONLY); -} - -void -daemonize_set_user(void) -{ - if (user_name == nullptr) - return; - - /* set gid */ - if (user_gid != (gid_t)-1 && user_gid != getgid() && - setgid(user_gid) == -1) { - FormatFatalSystemError("Failed to set group %d", - (int)user_gid); - } - -#ifdef _BSD_SOURCE - /* init supplementary groups - * (must be done before we change our uid) - */ - if (!had_group && - /* no need to set the new user's supplementary groups if - we are already this user */ - user_uid != getuid() && - initgroups(user_name, user_gid) == -1) { - FormatFatalSystemError("Failed to set supplementary groups " - "of user \"%s\"", - user_name); - } -#endif - - /* set uid */ - if (user_uid != (uid_t)-1 && user_uid != getuid() && - setuid(user_uid) == -1) { - FormatFatalSystemError("Failed to set user \"%s\"", - user_name); - } -} - -void -daemonize_begin(bool detach) -{ - /* release the current working directory */ - if (chdir("/") < 0) - FatalError("problems changing to root directory"); - - if (!detach) - /* the rest of this function deals with detaching the - process */ - return; - - /* do this before daemonizing so we can fail gracefully if we - can't write to the pid file */ - PidFile pidfile2(pidfile); - - /* flush all file handles before duplicating the buffers */ - - fflush(nullptr); - - /* create a pipe to synchronize the parent and the child */ - - int fds[2]; - if (pipe(fds) < 0) - FatalSystemError("pipe() failed"); - - /* move to a child process */ - - pid_t pid = fork(); - if (pid < 0) - FatalSystemError("fork() failed"); - - if (pid == 0) { - /* in the child process */ - - pidfile2.Close(); - close(fds[0]); - detach_fd = fds[1]; - - /* detach from the current session */ - setsid(); - - /* continue starting MPD */ - return; - } - - /* in the parent process */ - - close(fds[1]); - - int result; - ssize_t nbytes = read(fds[0], &result, sizeof(result)); - if (nbytes == (ssize_t)sizeof(result)) { - /* the child process was successful */ - pidfile2.Write(pid); - exit(EXIT_SUCCESS); - } - - /* something bad happened in the child process */ - - pidfile2.Delete(pidfile); - - int status; - pid_t pid2 = waitpid(pid, &status, 0); - if (pid2 < 0) - FatalSystemError("waitpid() failed"); - - if (WIFSIGNALED(status)) - FormatFatalError("MPD died from signal %d%s", WTERMSIG(status), - WCOREDUMP(status) ? " (core dumped)" : ""); - - exit(WEXITSTATUS(status)); -} - -void -daemonize_commit() -{ - if (detach_fd >= 0) { - /* tell the parent process to let go of us and exit - indicating success */ - int result = 0; - write(detach_fd, &result, sizeof(result)); - close(detach_fd); - } else - /* the pidfile was not written by the parent because - there is no parent - do it now */ - PidFile(pidfile).Write(); -} - -void -daemonize_init(const char *user, const char *group, AllocatedPath &&_pidfile) -{ - if (user) { - struct passwd *pwd = getpwnam(user); - if (pwd == nullptr) - FormatFatalError("no such user \"%s\"", user); - - user_uid = pwd->pw_uid; - user_gid = pwd->pw_gid; - - user_name = strdup(user); - - /* this is needed by libs such as arts */ - setenv("HOME", pwd->pw_dir, true); - } - - if (group) { - struct group *grp = getgrnam(group); - if (grp == nullptr) - FormatFatalError("no such group \"%s\"", group); - user_gid = grp->gr_gid; - had_group = true; - } - - - pidfile = std::move(_pidfile); -} - -void -daemonize_finish(void) -{ - if (!pidfile.IsNull()) { - RemoveFile(pidfile); - pidfile = AllocatedPath::Null(); - } - - free(user_name); -} - -#endif diff --git a/src/Daemon.hxx b/src/Daemon.hxx deleted file mode 100644 index fe5681511..000000000 --- a/src/Daemon.hxx +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (C) 2003-2014 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef MPD_DAEMON_HXX -#define MPD_DAEMON_HXX - -class AllocatedPath; - -#ifndef WIN32 -void -daemonize_init(const char *user, const char *group, AllocatedPath &&pidfile); -#else -static inline void -daemonize_init(const char *user, const char *group, AllocatedPath &&pidfile) -{ (void)user; (void)group; (void)pidfile; } -#endif - -#ifndef WIN32 -void -daemonize_finish(void); -#else -static inline void -daemonize_finish(void) -{ /* nop */ } -#endif - -/** - * Kill the MPD which is currently running, pid determined from the - * pid file. - */ -#ifndef WIN32 -void -daemonize_kill(void); -#else -#include "system/FatalError.hxx" -static inline void -daemonize_kill(void) -{ - FatalError("--kill is not available on WIN32"); -} -#endif - -/** - * Close stdin (fd 0) and re-open it as /dev/null. - */ -#ifndef WIN32 -void -daemonize_close_stdin(void); -#else -static inline void -daemonize_close_stdin(void) {} -#endif - -/** - * Change to the configured Unix user. - */ -#ifndef WIN32 -void -daemonize_set_user(void); -#else -static inline void -daemonize_set_user(void) -{ /* nop */ } -#endif - -#ifndef WIN32 -void -daemonize_begin(bool detach); -#else -static inline void -daemonize_begin(bool detach) -{ (void)detach; } -#endif - -#ifndef WIN32 -void -daemonize_commit(); -#else -static inline void -daemonize_commit() {} -#endif - -#endif diff --git a/src/Main.cxx b/src/Main.cxx index 94b510de3..912e28a62 100644 --- a/src/Main.cxx +++ b/src/Main.cxx @@ -41,7 +41,6 @@ #include "tag/TagConfig.hxx" #include "ReplayGainConfig.hxx" #include "Idle.hxx" -#include "SignalHandlers.hxx" #include "Log.hxx" #include "LogInit.hxx" #include "GlobalEvents.hxx" @@ -56,7 +55,8 @@ #include "decoder/DecoderList.hxx" #include "AudioConfig.hxx" #include "pcm/PcmConvert.hxx" -#include "Daemon.hxx" +#include "unix/SignalHandlers.hxx" +#include "unix/Daemon.hxx" #include "system/FatalError.hxx" #include "util/Error.hxx" #include "util/Domain.hxx" diff --git a/src/PidFile.hxx b/src/PidFile.hxx deleted file mode 100644 index a242c7810..000000000 --- a/src/PidFile.hxx +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2003-2014 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef MPD_PID_FILE_HXX -#define MPD_PID_FILE_HXX - -#include "fs/FileSystem.hxx" -#include "fs/AllocatedPath.hxx" -#include "Log.hxx" - -#include -#include -#include -#include - -class PidFile { - FILE *file; - -public: - PidFile(const AllocatedPath &path):file(nullptr) { - if (path.IsNull()) - return; - - file = FOpen(path, "w"); - if (file == nullptr) { - const std::string utf8 = path.ToUTF8(); - FormatFatalSystemError("Failed to create pid file \"%s\"", - path.c_str()); - } - } - - PidFile(const PidFile &) = delete; - - void Close() { - if (file == nullptr) - return; - - fclose(file); - } - - void Delete(const AllocatedPath &path) { - if (file == nullptr) { - assert(path.IsNull()); - return; - } - - assert(!path.IsNull()); - - fclose(file); - RemoveFile(path); - } - - void Write(pid_t pid) { - if (file == nullptr) - return; - - fprintf(file, "%lu\n", (unsigned long)pid); - fclose(file); - } - - void Write() { - if (file == nullptr) - return; - - Write(getpid()); - } -}; - -#endif diff --git a/src/SignalHandlers.cxx b/src/SignalHandlers.cxx deleted file mode 100644 index 4aef4fa71..000000000 --- a/src/SignalHandlers.cxx +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2003-2014 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "config.h" -#include "SignalHandlers.hxx" -#include "event/SignalMonitor.hxx" - -#ifndef WIN32 - -#include "Log.hxx" -#include "LogInit.hxx" -#include "event/Loop.hxx" -#include "system/FatalError.hxx" -#include "util/Domain.hxx" - -#include - -static constexpr Domain signal_handlers_domain("signal_handlers"); - -static void -HandleShutdownSignal() -{ - SignalMonitorGetEventLoop().Break(); -} - -static void -x_sigaction(int signum, const struct sigaction *act) -{ - if (sigaction(signum, act, NULL) < 0) - FatalSystemError("sigaction() failed"); -} - -static void -handle_reload_event(void) -{ - LogDebug(signal_handlers_domain, "got SIGHUP, reopening log files"); - cycle_log_files(); -} - -#endif - -void -SignalHandlersInit(EventLoop &loop) -{ - SignalMonitorInit(loop); - -#ifndef WIN32 - struct sigaction sa; - - sa.sa_flags = 0; - sigemptyset(&sa.sa_mask); - sa.sa_handler = SIG_IGN; - x_sigaction(SIGPIPE, &sa); - - SignalMonitorRegister(SIGINT, HandleShutdownSignal); - SignalMonitorRegister(SIGTERM, HandleShutdownSignal); - - SignalMonitorRegister(SIGHUP, handle_reload_event); -#endif -} - -void -SignalHandlersFinish() -{ - SignalMonitorFinish(); -} diff --git a/src/SignalHandlers.hxx b/src/SignalHandlers.hxx deleted file mode 100644 index 551b373c1..000000000 --- a/src/SignalHandlers.hxx +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2003-2014 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef MPD_SIGNAL_HANDLERS_HXX -#define MPD_SIGNAL_HANDLERS_HXX - -class EventLoop; - -void -SignalHandlersInit(EventLoop &loop); - -void -SignalHandlersFinish(); - -#endif diff --git a/src/unix/Daemon.cxx b/src/unix/Daemon.cxx new file mode 100644 index 000000000..490b2def5 --- /dev/null +++ b/src/unix/Daemon.cxx @@ -0,0 +1,268 @@ +/* + * Copyright (C) 2003-2014 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "Daemon.hxx" +#include "system/FatalError.hxx" +#include "fs/AllocatedPath.hxx" +#include "fs/FileSystem.hxx" +#include "util/Domain.hxx" +#include "PidFile.hxx" +#include "Log.hxx" + +#include +#include +#include + +#ifndef WIN32 +#include +#include +#include +#include +#endif + +static constexpr Domain daemon_domain("daemon"); + +#ifndef WIN32 + +/** the Unix user name which MPD runs as */ +static char *user_name; + +/** the Unix user id which MPD runs as */ +static uid_t user_uid = (uid_t)-1; + +/** the Unix group id which MPD runs as */ +static gid_t user_gid = (gid_t)-1; + +/** the absolute path of the pidfile */ +static AllocatedPath pidfile = AllocatedPath::Null(); + +/* whether "group" conf. option was given */ +static bool had_group = false; + +/** + * The write end of a pipe that is used to notify the parent process + * that initialization has finished and that it should detach. + */ +static int detach_fd = -1; + +void +daemonize_kill(void) +{ + FILE *fp; + int pid, ret; + + if (pidfile.IsNull()) + FatalError("no pid_file specified in the config file"); + + fp = FOpen(pidfile, "r"); + if (fp == nullptr) { + const std::string utf8 = pidfile.ToUTF8(); + FormatFatalSystemError("Unable to open pid file \"%s\"", + utf8.c_str()); + } + + if (fscanf(fp, "%i", &pid) != 1) { + const std::string utf8 = pidfile.ToUTF8(); + FormatFatalError("unable to read the pid from file \"%s\"", + utf8.c_str()); + } + fclose(fp); + + ret = kill(pid, SIGTERM); + if (ret < 0) + FormatFatalSystemError("unable to kill process %i", + int(pid)); + + exit(EXIT_SUCCESS); +} + +void +daemonize_close_stdin(void) +{ + close(STDIN_FILENO); + open("/dev/null", O_RDONLY); +} + +void +daemonize_set_user(void) +{ + if (user_name == nullptr) + return; + + /* set gid */ + if (user_gid != (gid_t)-1 && user_gid != getgid() && + setgid(user_gid) == -1) { + FormatFatalSystemError("Failed to set group %d", + (int)user_gid); + } + +#ifdef _BSD_SOURCE + /* init supplementary groups + * (must be done before we change our uid) + */ + if (!had_group && + /* no need to set the new user's supplementary groups if + we are already this user */ + user_uid != getuid() && + initgroups(user_name, user_gid) == -1) { + FormatFatalSystemError("Failed to set supplementary groups " + "of user \"%s\"", + user_name); + } +#endif + + /* set uid */ + if (user_uid != (uid_t)-1 && user_uid != getuid() && + setuid(user_uid) == -1) { + FormatFatalSystemError("Failed to set user \"%s\"", + user_name); + } +} + +void +daemonize_begin(bool detach) +{ + /* release the current working directory */ + if (chdir("/") < 0) + FatalError("problems changing to root directory"); + + if (!detach) + /* the rest of this function deals with detaching the + process */ + return; + + /* do this before daemonizing so we can fail gracefully if we + can't write to the pid file */ + PidFile pidfile2(pidfile); + + /* flush all file handles before duplicating the buffers */ + + fflush(nullptr); + + /* create a pipe to synchronize the parent and the child */ + + int fds[2]; + if (pipe(fds) < 0) + FatalSystemError("pipe() failed"); + + /* move to a child process */ + + pid_t pid = fork(); + if (pid < 0) + FatalSystemError("fork() failed"); + + if (pid == 0) { + /* in the child process */ + + pidfile2.Close(); + close(fds[0]); + detach_fd = fds[1]; + + /* detach from the current session */ + setsid(); + + /* continue starting MPD */ + return; + } + + /* in the parent process */ + + close(fds[1]); + + int result; + ssize_t nbytes = read(fds[0], &result, sizeof(result)); + if (nbytes == (ssize_t)sizeof(result)) { + /* the child process was successful */ + pidfile2.Write(pid); + exit(EXIT_SUCCESS); + } + + /* something bad happened in the child process */ + + pidfile2.Delete(pidfile); + + int status; + pid_t pid2 = waitpid(pid, &status, 0); + if (pid2 < 0) + FatalSystemError("waitpid() failed"); + + if (WIFSIGNALED(status)) + FormatFatalError("MPD died from signal %d%s", WTERMSIG(status), + WCOREDUMP(status) ? " (core dumped)" : ""); + + exit(WEXITSTATUS(status)); +} + +void +daemonize_commit() +{ + if (detach_fd >= 0) { + /* tell the parent process to let go of us and exit + indicating success */ + int result = 0; + write(detach_fd, &result, sizeof(result)); + close(detach_fd); + } else + /* the pidfile was not written by the parent because + there is no parent - do it now */ + PidFile(pidfile).Write(); +} + +void +daemonize_init(const char *user, const char *group, AllocatedPath &&_pidfile) +{ + if (user) { + struct passwd *pwd = getpwnam(user); + if (pwd == nullptr) + FormatFatalError("no such user \"%s\"", user); + + user_uid = pwd->pw_uid; + user_gid = pwd->pw_gid; + + user_name = strdup(user); + + /* this is needed by libs such as arts */ + setenv("HOME", pwd->pw_dir, true); + } + + if (group) { + struct group *grp = getgrnam(group); + if (grp == nullptr) + FormatFatalError("no such group \"%s\"", group); + user_gid = grp->gr_gid; + had_group = true; + } + + + pidfile = std::move(_pidfile); +} + +void +daemonize_finish(void) +{ + if (!pidfile.IsNull()) { + RemoveFile(pidfile); + pidfile = AllocatedPath::Null(); + } + + free(user_name); +} + +#endif diff --git a/src/unix/Daemon.hxx b/src/unix/Daemon.hxx new file mode 100644 index 000000000..fe5681511 --- /dev/null +++ b/src/unix/Daemon.hxx @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2003-2014 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_DAEMON_HXX +#define MPD_DAEMON_HXX + +class AllocatedPath; + +#ifndef WIN32 +void +daemonize_init(const char *user, const char *group, AllocatedPath &&pidfile); +#else +static inline void +daemonize_init(const char *user, const char *group, AllocatedPath &&pidfile) +{ (void)user; (void)group; (void)pidfile; } +#endif + +#ifndef WIN32 +void +daemonize_finish(void); +#else +static inline void +daemonize_finish(void) +{ /* nop */ } +#endif + +/** + * Kill the MPD which is currently running, pid determined from the + * pid file. + */ +#ifndef WIN32 +void +daemonize_kill(void); +#else +#include "system/FatalError.hxx" +static inline void +daemonize_kill(void) +{ + FatalError("--kill is not available on WIN32"); +} +#endif + +/** + * Close stdin (fd 0) and re-open it as /dev/null. + */ +#ifndef WIN32 +void +daemonize_close_stdin(void); +#else +static inline void +daemonize_close_stdin(void) {} +#endif + +/** + * Change to the configured Unix user. + */ +#ifndef WIN32 +void +daemonize_set_user(void); +#else +static inline void +daemonize_set_user(void) +{ /* nop */ } +#endif + +#ifndef WIN32 +void +daemonize_begin(bool detach); +#else +static inline void +daemonize_begin(bool detach) +{ (void)detach; } +#endif + +#ifndef WIN32 +void +daemonize_commit(); +#else +static inline void +daemonize_commit() {} +#endif + +#endif diff --git a/src/unix/PidFile.hxx b/src/unix/PidFile.hxx new file mode 100644 index 000000000..a242c7810 --- /dev/null +++ b/src/unix/PidFile.hxx @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2003-2014 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_PID_FILE_HXX +#define MPD_PID_FILE_HXX + +#include "fs/FileSystem.hxx" +#include "fs/AllocatedPath.hxx" +#include "Log.hxx" + +#include +#include +#include +#include + +class PidFile { + FILE *file; + +public: + PidFile(const AllocatedPath &path):file(nullptr) { + if (path.IsNull()) + return; + + file = FOpen(path, "w"); + if (file == nullptr) { + const std::string utf8 = path.ToUTF8(); + FormatFatalSystemError("Failed to create pid file \"%s\"", + path.c_str()); + } + } + + PidFile(const PidFile &) = delete; + + void Close() { + if (file == nullptr) + return; + + fclose(file); + } + + void Delete(const AllocatedPath &path) { + if (file == nullptr) { + assert(path.IsNull()); + return; + } + + assert(!path.IsNull()); + + fclose(file); + RemoveFile(path); + } + + void Write(pid_t pid) { + if (file == nullptr) + return; + + fprintf(file, "%lu\n", (unsigned long)pid); + fclose(file); + } + + void Write() { + if (file == nullptr) + return; + + Write(getpid()); + } +}; + +#endif diff --git a/src/unix/SignalHandlers.cxx b/src/unix/SignalHandlers.cxx new file mode 100644 index 000000000..4aef4fa71 --- /dev/null +++ b/src/unix/SignalHandlers.cxx @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2003-2014 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "SignalHandlers.hxx" +#include "event/SignalMonitor.hxx" + +#ifndef WIN32 + +#include "Log.hxx" +#include "LogInit.hxx" +#include "event/Loop.hxx" +#include "system/FatalError.hxx" +#include "util/Domain.hxx" + +#include + +static constexpr Domain signal_handlers_domain("signal_handlers"); + +static void +HandleShutdownSignal() +{ + SignalMonitorGetEventLoop().Break(); +} + +static void +x_sigaction(int signum, const struct sigaction *act) +{ + if (sigaction(signum, act, NULL) < 0) + FatalSystemError("sigaction() failed"); +} + +static void +handle_reload_event(void) +{ + LogDebug(signal_handlers_domain, "got SIGHUP, reopening log files"); + cycle_log_files(); +} + +#endif + +void +SignalHandlersInit(EventLoop &loop) +{ + SignalMonitorInit(loop); + +#ifndef WIN32 + struct sigaction sa; + + sa.sa_flags = 0; + sigemptyset(&sa.sa_mask); + sa.sa_handler = SIG_IGN; + x_sigaction(SIGPIPE, &sa); + + SignalMonitorRegister(SIGINT, HandleShutdownSignal); + SignalMonitorRegister(SIGTERM, HandleShutdownSignal); + + SignalMonitorRegister(SIGHUP, handle_reload_event); +#endif +} + +void +SignalHandlersFinish() +{ + SignalMonitorFinish(); +} diff --git a/src/unix/SignalHandlers.hxx b/src/unix/SignalHandlers.hxx new file mode 100644 index 000000000..551b373c1 --- /dev/null +++ b/src/unix/SignalHandlers.hxx @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2003-2014 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_SIGNAL_HANDLERS_HXX +#define MPD_SIGNAL_HANDLERS_HXX + +class EventLoop; + +void +SignalHandlersInit(EventLoop &loop); + +void +SignalHandlersFinish(); + +#endif -- cgit v1.2.3