#include <config.h>
#include "daemon.h"
+#include "daemon-private.h"
#include <stdio.h>
#include <stdlib.h>
#include "poll-loop.h"
#include "vlog.h"
-VLOG_DEFINE_THIS_MODULE(daemon);
+VLOG_DEFINE_THIS_MODULE(daemon_windows);
static bool service_create; /* Was --service specified? */
static bool service_started; /* Have we dispatched service to start? */
* unexpectedly? */
static bool monitor;
-static bool detach; /* Was --detach specified? */
-static bool detached; /* Running as the child process. */
-static HANDLE write_handle; /* End of pipe to write to parent. */
+bool detach; /* Was --detach specified? */
+static bool detached; /* Running as the child process. */
+static HANDLE write_handle; /* End of pipe to write to parent. */
+
+char *pidfile; /* --pidfile: Name of pidfile (null if none). */
+static FILE *filep_pidfile; /* File pointer to access the pidfile. */
/* Handle to the Services Manager and the created service. */
static SC_HANDLE manager, service;
exit(0);
}
-/* Will daemonize() really detach? */
-bool
-get_detach()
+static void
+unlink_pidfile(void)
{
- return detach;
+ if (filep_pidfile) {
+ fclose(filep_pidfile);
+ }
+ if (pidfile) {
+ unlink(pidfile);
+ }
}
-void
-daemon_save_fd(int fd OVS_UNUSED)
+/* If a pidfile has been configured, creates it and stores the running
+ * process's pid in it. Ensures that the pidfile will be deleted when the
+ * process exits. */
+static void
+make_pidfile(void)
{
-}
+ int error;
+
+ error = GetFileAttributes(pidfile);
+ if (error != INVALID_FILE_ATTRIBUTES) {
+ /* pidfile exists. Try to unlink() it. */
+ error = unlink(pidfile);
+ if (error) {
+ VLOG_FATAL("Failed to delete existing pidfile %s (%s)", pidfile,
+ ovs_strerror(errno));
+ }
+ }
-void
-daemonize(void)
-{
+ filep_pidfile = fopen(pidfile, "w");
+ if (filep_pidfile == NULL) {
+ VLOG_FATAL("failed to open %s (%s)", pidfile, ovs_strerror(errno));
+ }
+
+ fatal_signal_add_hook(unlink_pidfile, NULL, NULL, true);
+
+ fprintf(filep_pidfile, "%d\n", _getpid());
+ if (fflush(filep_pidfile) == EOF) {
+ VLOG_FATAL("Failed to write into the pidfile %s", pidfile);
+ }
+
+ /* Don't close the pidfile till the process exits. */
}
void daemonize_start(void)
{
+ if (pidfile) {
+ make_pidfile();
+ }
}
void
* communicate with the parent to inform that the child is ready. */
if (detached) {
int error;
+
+ close_standard_fds();
+
error = WriteFile(write_handle, "a", 1, NULL, NULL);
if (!error) {
VLOG_FATAL("Failed to communicate with the parent (%s)",
service_complete();
}
+
+/* Returns the file name that would be used for a pidfile if 'name' were
+ * provided to set_pidfile(). The caller must free the returned string. */
+char *
+make_pidfile_name(const char *name)
+{
+ if (name && strchr(name, ':')) {
+ return strdup(name);
+ } else {
+ return xasprintf("%s/%s.pid", ovs_rundir(), program_name);
+ }
+}