From 93fb44ed0fb063ced0504dac8f12334606c18b25 Mon Sep 17 00:00:00 2001 From: Jan Friesse Date: Mon, 2 Aug 2010 12:36:20 +0000 Subject: [PATCH] Allow running only one instance of Corosync Patch makes Corosync more compliant with common practices for writing daemon. It creates pid file (usually /var/run/corosync.pid) and flocks it. So only one instance of Corosync can be executed now. git-svn-id: http://svn.fedorahosted.org/svn/corosync/trunk@3010 fd59a12c-fef9-0310-b244-a6a79926bd2f --- exec/main.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++++ exec/util.h | 4 +- init/generic.in | 2 - 3 files changed, 104 insertions(+), 3 deletions(-) diff --git a/exec/main.c b/exec/main.c index 4ddb5f2b..56d4316c 100644 --- a/exec/main.c +++ b/exec/main.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -139,6 +140,8 @@ static pthread_t corosync_exit_thread; static sem_t corosync_exit_sem; +static const char *corosync_lock_file = LOCALSTATEDIR"/run/corosync.pid"; + static void serialize_unlock (void); hdb_handle_t corosync_poll_handle_get (void) @@ -170,6 +173,11 @@ static void unlink_all_completed (void) poll_stop (corosync_poll_handle); totempg_finalize (); + /* + * Remove pid lock file + */ + unlink (corosync_lock_file); + corosync_exit_error (AIS_DONE_EXIT); } @@ -1367,6 +1375,93 @@ static void main_service_ready (void) } +static enum e_ais_done corosync_flock (const char *lockfile, pid_t pid) +{ + struct flock lock; + enum e_ais_done err; + char pid_s[17]; + int fd_flag; + int lf; + + err = AIS_DONE_EXIT; + + lf = open (lockfile, O_WRONLY | O_CREAT, 0640); + if (lf == -1) { + log_printf (LOGSYS_LEVEL_ERROR, "Corosync Executive couldn't create lock file.\n"); + return (AIS_DONE_AQUIRE_LOCK); + } + +retry_fcntl: + lock.l_type = F_WRLCK; + lock.l_start = 0; + lock.l_whence = SEEK_SET; + lock.l_len = 0; + if (fcntl (lf, F_SETLK, &lock) == -1) { + switch (errno) { + case EINTR: + goto retry_fcntl; + break; + case EAGAIN: + case EACCES: + log_printf (LOGSYS_LEVEL_ERROR, "Another Corosync instance is already running.\n"); + err = AIS_DONE_ALREADY_RUNNING; + goto error_close; + break; + default: + log_printf (LOGSYS_LEVEL_ERROR, "Corosync Executive couldn't aquire lock. Error was %s\n", + strerror(errno)); + err = AIS_DONE_AQUIRE_LOCK; + goto error_close; + break; + } + } + + if (ftruncate (lf, 0) == -1) { + log_printf (LOGSYS_LEVEL_ERROR, "Corosync Executive couldn't truncate lock file. Error was %s\n", + strerror (errno)); + err = AIS_DONE_AQUIRE_LOCK; + goto error_close_unlink; + } + + memset (pid_s, 0, sizeof (pid_s)); + snprintf (pid_s, sizeof (pid_s) - 1, "%u\n", pid); + +retry_write: + if (write (lf, pid_s, strlen (pid_s)) != strlen (pid_s)) { + if (errno == EINTR) { + goto retry_write; + } else { + log_printf (LOGSYS_LEVEL_ERROR, "Corosync Executive couldn't write pid to lock file. " + "Error was %s\n", strerror (errno)); + err = AIS_DONE_AQUIRE_LOCK; + goto error_close_unlink; + } + } + + if ((fd_flag = fcntl (lf, F_GETFD, 0)) == -1) { + log_printf (LOGSYS_LEVEL_ERROR, "Corosync Executive couldn't get close-on-exec flag from lock file. " + "Error was %s\n", strerror (errno)); + err = AIS_DONE_AQUIRE_LOCK; + goto error_close_unlink; + } + fd_flag |= FD_CLOEXEC; + if (fcntl (lf, F_SETFD, fd_flag) == -1) { + log_printf (LOGSYS_LEVEL_ERROR, "Corosync Executive couldn't set close-on-exec flag to lock file. " + "Error was %s\n", strerror (errno)); + err = AIS_DONE_AQUIRE_LOCK; + goto error_close_unlink; + } + + return (err); + +error_close_unlink: + unlink (lockfile); +error_close: + close (lf); + + return (err); +} + int main (int argc, char **argv, char **envp) { const char *error_string; @@ -1386,6 +1481,7 @@ int main (int argc, char **argv, char **envp) struct stat stat_out; char corosync_lib_dir[PATH_MAX]; hdb_handle_t object_runtime_handle; + enum e_ais_done flock_err; #if defined(HAVE_PTHREAD_SPIN_LOCK) pthread_spin_init (&serialize_spin, 0); @@ -1436,6 +1532,7 @@ int main (int argc, char **argv, char **envp) log_printf (LOGSYS_LEVEL_NOTICE, "Corosync Cluster Engine ('%s'): started and ready to provide service.\n", VERSION); log_printf (LOGSYS_LEVEL_INFO, "Corosync built-in features:" PACKAGE_FEATURES "\n"); + (void)signal (SIGINT, sigintr_handler); (void)signal (SIGUSR2, sigusr2_handler); (void)signal (SIGSEGV, sigsegv_handler); @@ -1605,6 +1702,10 @@ int main (int argc, char **argv, char **envp) } logsys_fork_completed(); + if ((flock_err = corosync_flock (corosync_lock_file, getpid ())) != AIS_DONE_EXIT) { + corosync_exit_error (flock_err); + } + /* callthis after our fork() */ tsafe_init (envp); diff --git a/exec/util.h b/exec/util.h index 7b955368..ed3529ca 100644 --- a/exec/util.h +++ b/exec/util.h @@ -60,7 +60,9 @@ enum e_ais_done { AIS_DONE_INIT_SERVICES = 13, AIS_DONE_OUT_OF_MEMORY = 14, AIS_DONE_FATAL_ERR = 15, - AIS_DONE_DIR_NOT_PRESENT = 16 + AIS_DONE_DIR_NOT_PRESENT = 16, + AIS_DONE_AQUIRE_LOCK = 17, + AIS_DONE_ALREADY_RUNNING = 18, }; /* diff --git a/init/generic.in b/init/generic.in index 261ceafb..37235b95 100755 --- a/init/generic.in +++ b/init/generic.in @@ -90,7 +90,6 @@ start() sleep 2 if status $prog > /dev/null 2>&1; then touch $LOCK_FILE - pidof $prog > @LOCALSTATEDIR@/run/$prog.pid success else failure @@ -116,7 +115,6 @@ stop() done rm -f $LOCK_FILE - rm -f @LOCALSTATEDIR@/run/$prog.pid success echo } -- 2.39.5