From 9668922f8f15f3a7331465a55f2cafca61f31db1 Mon Sep 17 00:00:00 2001 From: Sergey Popov Date: Tue, 3 Jan 2012 03:48:26 +0400 Subject: [PATCH] Revert "remove unneeded fork(for now)" This reverts commit 955aeb64b7b504a4d1b652274affcfacf3d581aa. Implement pid file management and locking. Only single instance of daemon is allowed --- yasnd.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/yasnd.c b/yasnd.c index 65035d0..64b6418 100644 --- a/yasnd.c +++ b/yasnd.c @@ -8,6 +8,7 @@ #include "yasnd.h" cfg_t *cfg; // pointer to configuration structure +char pidfile[]="/var/run/yasnd.pid"; // pidfile path host_decl* hosts=NULL; // structure with hosts' definitions int hosts_count=0; // count of hosts int debug_flag=0; @@ -94,6 +95,28 @@ int cb_validate_host(cfg_t *cfg, cfg_opt_t *opt) return 0; // success } +void pidfile_init() +{ + int pidfile_d=open(pidfile,O_RDWR|O_CREAT,0640); + /* Can not open/create pidfile? */ + if (pidfile_d<0) + { + log_event("Error: can not open/create pid file"); + exit(EXIT_FAILURE); + } + /* Can not lock pidfile? */ + if (lockf(pidfile_d,F_TLOCK,0)<0) + { + log_event("Error: can not lock pid file, maybe another yasnd instance still running?"); + exit(EXIT_FAILURE); + } + /* First daemon instance continues */ + char pidstr[20]; + sprintf(pidstr,"%d\n",getpid()); + /* Record pid to pidfile and hold it */ + write(pidfile_d,pidstr,strlen(pidstr)); +} + void init() { static cfg_opt_t host_opts[] = { @@ -311,6 +334,8 @@ void signal_handler(int signum) // free hosts structures memory if (hosts!=NULL) free(hosts); + // remove pid file + remove(pidfile); } if (signum==SIGHUP) @@ -366,12 +391,29 @@ int main(int argc, char *argv[]) /* Our process ID and Session ID */ pid_t pid, sid; + /* Fork off the parent process */ + pid = fork(); + if (pid < 0) { + exit(EXIT_FAILURE); + } + /* If we got a good PID, then we can exit the parent process. */ + if (pid > 0) { + exit(EXIT_SUCCESS); + } + /* Change the file mode mask */ umask(0); /* Open any logs here */ openlog("yasnd", LOG_PID|LOG_CONS, LOG_USER); + /* Create a new SID for the child process */ + sid = setsid(); + if (sid < 0) { + /* Log the failure */ + exit(EXIT_FAILURE); + } + /* Change the current working directory */ if ((chdir("/")) < 0) { /* Log the failure */ @@ -383,6 +425,9 @@ int main(int argc, char *argv[]) close(STDOUT_FILENO); close(STDERR_FILENO); + // create pid file and write current process pid + pidfile_init(); + // initialize IPC queue and create process // that will watch for new messages in it ipc_init();