aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/unistd.h19
-rw-r--r--src/unistd/daemonise.c53
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;
+}
+