Sfoglia il codice sorgente

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
Jan Friesse 15 anni fa
parent
commit
93fb44ed0f
3 ha cambiato i file con 104 aggiunte e 3 eliminazioni
  1. 101 0
      exec/main.c
  2. 3 1
      exec/util.h
  3. 0 2
      init/generic.in

+ 101 - 0
exec/main.c

@@ -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);
 

+ 3 - 1
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,
 };
 
 /*

+ 0 - 2
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
 }