]> git.proxmox.com Git - mirror_corosync.git/commitdiff
Allow running only one instance of Corosync
authorJan Friesse <jfriesse@redhat.com>
Mon, 2 Aug 2010 12:36:20 +0000 (12:36 +0000)
committerJan Friesse <jfriesse@redhat.com>
Mon, 2 Aug 2010 12:36:20 +0000 (12:36 +0000)
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
exec/util.h
init/generic.in

index 4ddb5f2b8a050ec92a96afe03ae5fdf9a08c7b16..56d4316c60ababb6c236115219e9bf33d2f0f2c5 100644 (file)
@@ -38,6 +38,7 @@
 #include <pthread.h>
 #include <assert.h>
 #include <sys/types.h>
+#include <sys/file.h>
 #include <sys/poll.h>
 #include <sys/uio.h>
 #include <sys/mman.h>
@@ -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);
 
index 7b955368eccc2de2e1a142e1157a02ab2b33c14a..ed3529ca596afa6de7859cde6a20c5e539b6909b 100644 (file)
@@ -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,
 };
 
 /*
index 261ceafb999b8b983964625301318cf974e21c83..37235b950c5f5f5c15e4f8fb547e0caf311a26cc 100755 (executable)
@@ -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
 }