In Windows, we cannot delete a file that has been opened. We use this feature to "lock" the pidfile.
Signed-off-by: Gurucharan Shetty <gshe...@nicira.com> --- lib/daemon-windows.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++ lib/daemon.h | 8 ++++- 2 files changed, 86 insertions(+), 1 deletion(-) diff --git a/lib/daemon-windows.c b/lib/daemon-windows.c index baa7520..b47b42e 100644 --- a/lib/daemon-windows.c +++ b/lib/daemon-windows.c @@ -34,6 +34,9 @@ static bool detach; /* Was --detach specified? */ static bool detached; /* Running as the child process. */ static HANDLE write_handle; /* pipe handle to write to the parent. */ +static 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; @@ -409,10 +412,59 @@ daemon_save_fd(int fd OVS_UNUSED) void daemonize(void) { + daemonize_start(); + daemonize_complete(); +} + +static void +unlink_pidfile(void) +{ + if (filep_pidfile) { + fclose(filep_pidfile); + } + if (pidfile) { + unlink(pidfile); + } +} + +/* 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)); + } + } + + 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 @@ -431,3 +483,30 @@ daemonize_complete(void) service_complete(); } + +/* Returns the file name that would be used for a pidfile if 'name' were + * provided to set_pidfile(). If 'name' is not provided, returns the default + * name based on rundir. The caller must free the returned string. */ +static char * +make_pidfile_name(const char *name) +{ + if (name && strchr(name, ':')) { + return strdup(name); + } else { + return xasprintf("%s/%s.pid", ovs_rundir(), program_name); + } +} + +/* Sets up a following call to daemonize() to create a pidfile named 'name'. + * If 'name' contains ':', then it is treated as an absolute path. + * Otherwise, it is taken relative to RUNDIR, which is $(prefix)/var/run by + * default. + * + * If 'name' is null, then program_name followed by ".pid" is used. */ +void +set_pidfile(const char *name) +{ + assert_single_threaded(); + free(pidfile); + pidfile = make_pidfile_name(name); +} diff --git a/lib/daemon.h b/lib/daemon.h index f4dced3..0b7dc5f 100644 --- a/lib/daemon.h +++ b/lib/daemon.h @@ -74,19 +74,20 @@ void set_detach(void); void daemon_set_monitor(void); -void set_pidfile(const char *name); void set_no_chdir(void); void ignore_existing_pidfile(void); pid_t read_pidfile(const char *name); #else #define DAEMON_OPTION_ENUMS \ OPT_DETACH, \ + OPT_PIDFILE, \ OPT_PIPE_HANDLE, \ OPT_SERVICE, \ OPT_SERVICE_MONITOR #define DAEMON_LONG_OPTIONS \ {"detach", no_argument, NULL, OPT_DETACH}, \ + {"pidfile", optional_argument, NULL, OPT_PIDFILE}, \ {"pipe-handle", required_argument, NULL, OPT_PIPE_HANDLE}, \ {"service", no_argument, NULL, OPT_SERVICE}, \ {"service-monitor", no_argument, NULL, OPT_SERVICE_MONITOR} @@ -95,6 +96,10 @@ pid_t read_pidfile(const char *name); case OPT_DETACH: \ break; \ \ + case OPT_PIDFILE: \ + set_pidfile(optarg); \ + break; \ + \ case OPT_PIPE_HANDLE: \ set_pipe_handle(optarg); \ break; \ @@ -117,6 +122,7 @@ void daemonize_complete(void); void daemon_usage(void); void service_start(int *argcp, char **argvp[]); void service_stop(void); +void set_pidfile(const char *name); bool should_service_stop(void); #endif /* daemon.h */ -- 1.7.9.5 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev