diff options
-rw-r--r-- | include/unistd.h | 19 | ||||
-rw-r--r-- | src/unistd/daemonise.c | 53 |
2 files changed, 68 insertions, 4 deletions
diff --git a/include/unistd.h b/include/unistd.h index 4629e8e..963bb96 100644 --- a/include/unistd.h +++ b/include/unistd.h @@ -1138,6 +1138,8 @@ int daemon(int, int) * should be used instead of /run for the runtime data-files * directory, in which the PID file is stored. * + * This is a slibc extension. + * * @etymology (Daemonise) the process! * * @param name The name of the daemon. Use a hardcoded value, @@ -1174,6 +1176,23 @@ int daemon(int, int) */ int daemonise(const char*, int) __GCC_ONLY(__attribute__((__nonnull__, __warn_unused_result__))); + +/** + * Remove the PID file created by `daemonise`. This shall + * always be called before exiting after calling `daemonise`, + * even if it failed. + * + * This is a slibc extension. + * + * @etymology (Un)link PID file created by `(daemonise)`! + * + * @return Zero on success, -1 on error. + * + * @throws Any error specified for unlink(3). + * + * @since Always. + */ +int undaemonise(void); #endif diff --git a/src/unistd/daemonise.c b/src/unistd/daemonise.c index a8fe3ab..f3ebe3a 100644 --- a/src/unistd/daemonise.c +++ b/src/unistd/daemonise.c @@ -21,6 +21,7 @@ #include <fcntl.h> #include <signal.h> #include <string.h> +#include <stdlib.h> #include <errno.h> #include <sys/resource.h> @@ -31,6 +32,11 @@ */ extern char** environ; +/** + * The pidfile created by `daemonise`. + */ +static char* __pidfile = NULL; + /** @@ -96,6 +102,8 @@ extern char** environ; * should be used instead of /run for the runtime data-files * directory, in which the PID file is stored. * + * This is a slibc extension. + * * @etymology (Daemonise) the process! * * @param name The name of the daemon. Use a hardcoded value, @@ -221,16 +229,24 @@ int daemonise(const char* name, int flags) run = getenv("XDG_RUNTIME_DIR"); if (run && *run) { - pidpath = alloca(sizeof("/.pid") + (strlen(run) + strlen(name)) * sizeof(char)); + pidpath = malloc(sizeof("/.pid") + (strlen(run) + strlen(name)) * sizeof(char)); + t (pidfile == NULL); stpcpy(stpcpy(stpcpy(stpcpy(pidpath, run), "/"), name), ".pid"); } else { - pidpath = alloca(sizeof("/run/.pid") + strlen(name) * sizeof(char)); + pidpath = malloc(sizeof("/run/.pid") + strlen(name) * sizeof(char)); + t (pidfile == NULL); stpcpy(stpcpy(stpcpy(pidpath, "/run/"), name), ".pid"); } fd = open(pidpath, O_WRONLY | O_CREAT | O_EXCL, 0644); - t (fd == -1); + if (fd == -1) + { + saved_errno = errno; + free(pidpath), pidpath = NULL; + errno = saved_errno; + goto fail; + } pid = getpid(); t (dprintf(fd, "%lli\n", (long long int)pid)) < 0; t (close(fd) && (errno != EINTR)); @@ -260,12 +276,13 @@ int daemonise(const char* name, int flags) { if (flags & DAEMONISE_KEEP_STDERR) return -1; + undaemonise(); abort(); /* Do not overcomplicate things, just abort in this unlikely event. */ } return 0; fail: - saved_errno = err; + saved_errno = errno; if (pipe_rw[0] >= 0) close(pipe_rw[0]); if (pipe_rw[1] >= 0) close(pipe_rw[1]); if (fd >= 0) close(fd); @@ -273,3 +290,31 @@ int daemonise(const char* name, int flags) return -1; } + +/** + * Remove the PID file created by `daemonise`. This shall + * always be called before exiting after calling `daemonise`, + * even if it failed. + * + * This is a slibc extension. + * + * @etymology (Un)link PID file created by `(daemonise)`! + * + * @return Zero on success, -1 on error. + * + * @throws Any error specified for unlink(3). + * + * @since Always. + */ +int undaemonise(void) +{ + int r, saved_errno; + if (pidfile == NULL) + return 0; + r = unlink(pidfile); + saved_errno = errno; + free(pidfile), pidfile = NULL; + errno = saved_errno; + return r; +} + |