diff --git a/cpuplugd/cpuplugd.h b/cpuplugd/cpuplugd.h index 5c847d6f..673054ef 100644 --- a/cpuplugd/cpuplugd.h +++ b/cpuplugd/cpuplugd.h @@ -197,10 +197,10 @@ int is_online(int cpuid); long get_cmmpages_size(); void parse_options(int argc, char **argv); void check_if_started_twice(); -void store_pid(void); void handle_signals(void); void handle_sighup(void); void reload_daemon(void); +int daemonize(void); int check_cmmfiles(void); void check_config(); void set_cmm_pages(long size); diff --git a/cpuplugd/daemon.c b/cpuplugd/daemon.c index f02a55d7..9820eba5 100644 --- a/cpuplugd/daemon.c +++ b/cpuplugd/daemon.c @@ -9,6 +9,10 @@ * it under the terms of the MIT license. See LICENSE for details. */ +#include +#include +#include + #include "cpuplugd.h" const char *name = NAME; @@ -49,7 +53,7 @@ void print_version() /* * Store daemon's pid so it can be stopped */ -void store_pid(void) +static int store_pid(void) { FILE *filp; @@ -57,10 +61,62 @@ void store_pid(void) if (!filp) { cpuplugd_error("cannot open pid file %s: %s\n", pid_file, strerror(errno)); - exit(1); + return -1; } fprintf(filp, "%d\n", getpid()); fclose(filp); + return 0; +} + +/* + * Run daemon in background and write pid file + */ +int daemonize(void) +{ + int fd, pipe_fds[2], startup_rc = 1; + pid_t pid; + + if (pipe(pipe_fds) == -1) { + cpuplugd_error("cannot create pipe\n"); + return -1; + } + pid = fork(); + if (pid < 0) + goto close_pipe; + if (pid != 0) { + /* Wait for startup return code from daemon */ + if (read(pipe_fds[0], &startup_rc, sizeof(startup_rc)) == -1) + cpuplugd_error("cannot read from pipe\n"); + /* On success daemon has written pid file at this point */ + exit(startup_rc); + } + /* Create new session */ + if (setsid() < 0) + goto notify_parent; + /* Redirect stdin/out/err to /dev/null */ + fd = open("/dev/null", O_RDWR, 0); + if (fd == -1) + goto notify_parent; + if (dup2(fd, STDIN_FILENO) < 0) + goto notify_parent; + if (dup2(fd, STDOUT_FILENO) < 0) + goto notify_parent; + if (dup2(fd, STDERR_FILENO) < 0) + goto notify_parent; + /* Create pid file */ + if (store_pid() < 0) + goto notify_parent; + startup_rc = 0; +notify_parent: + /* Inform waiting parent about startup return code */ + if (write(pipe_fds[1], &startup_rc, sizeof(startup_rc)) == -1) { + cpuplugd_error("cannot write to pipe\n"); + startup_rc = 1; + } +close_pipe: + close(pipe_fds[0]); + close(pipe_fds[1]); + return startup_rc ? -1 : 0; } /* diff --git a/cpuplugd/main.c b/cpuplugd/main.c index 0f55a7fe..d889d0bc 100644 --- a/cpuplugd/main.c +++ b/cpuplugd/main.c @@ -418,13 +418,11 @@ int main(int argc, char *argv[]) check_config(); if (!foreground) { - rc = daemon(1, 0); + rc = daemonize(); if (rc < 0) cpuplugd_exit("Detach from terminal failed: %s\n", strerror(errno)); } - /* Store daemon pid */ - store_pid(); /* Unlock lock file */ flock(fd, LOCK_UN); close(fd); diff --git a/systemd/cpuplugd.service.in b/systemd/cpuplugd.service.in index 6724f2bd..0d657b00 100644 --- a/systemd/cpuplugd.service.in +++ b/systemd/cpuplugd.service.in @@ -13,10 +13,11 @@ Documentation=man:cpuplugd(8) man:cpuplugd.conf(5) After=remote-fs.target [Service] -ExecStart=@usrsbin_path@/cpuplugd -f -c @sysconf_path@/cpuplugd.conf +ExecStart=@usrsbin_path@/cpuplugd -c @sysconf_path@/cpuplugd.conf ExecReload=/bin/kill -HUP $MAINPID KillMode=process -Type=simple +Type=forking +PIDFile=/var/run/cpuplugd.pid [Install] WantedBy=multi-user.target