[Ocfs2-tools-devel] [PATCH 2/2] o2hbmonitor: Limit number of active instances

Sunil Mushran sunil.mushran at oracle.com
Thu Dec 2 18:33:50 PST 2010


Patch attempts to disallow multiple instances of o2hbmonitor
running at the same time.

Signed-off-by: Sunil Mushran <sunil.mushran at oracle.com>
---
 o2monitor/Makefile      |    2 +-
 o2monitor/o2hbmonitor.c |   85 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 86 insertions(+), 1 deletions(-)

diff --git a/o2monitor/Makefile b/o2monitor/Makefile
index 961eafa..6392b96 100644
--- a/o2monitor/Makefile
+++ b/o2monitor/Makefile
@@ -21,6 +21,6 @@ OBJS = $(subst .c,.o,$(CFILES))
 DIST_FILES = $(CFILES) $(HFILES)
 
 o2hbmonitor: $(OBJS)
-	$(LINK)
+	$(LINK) -lrt
 
 include $(TOPDIR)/Postamble.make
diff --git a/o2monitor/o2hbmonitor.c b/o2monitor/o2hbmonitor.c
index 58e9280..44acb3a 100644
--- a/o2monitor/o2hbmonitor.c
+++ b/o2monitor/o2hbmonitor.c
@@ -43,6 +43,9 @@
 #include <libgen.h>
 #include <syslog.h>
 #include <errno.h>
+#include <sys/ipc.h>
+#include <semaphore.h>
+#include <signal.h>
 
 #define SYS_CONFIG_DIR			"/sys/kernel/config"
 #define O2HB_CLUSTER_DIR		SYS_CONFIG_DIR"/cluster"
@@ -71,6 +74,22 @@ unsigned long dead_threshold_in_ms;
 unsigned long warn_threshold_in_ms;
 unsigned long poll_in_secs;
 
+sem_t *sem;
+char sem_name[NAME_MAX - 4];
+int sem_taken;
+
+static void handler(int sig)
+{
+	if (sem_taken) {
+		sem_unlink(sem_name);
+		sem_post(sem);
+		sem_close(sem);
+	}
+
+	syslog(LOG_INFO, "Exiting\n");
+	exit(0);
+}
+
 static void show_version(void)
 {
 	fprintf(stderr, "%s %s\n", progname, VERSION);
@@ -278,6 +297,8 @@ static void monitor(void)
 {
 	int ret;
 
+	syslog(LOG_INFO, "Starting\n");
+
 	while (1) {
 		if (!is_cluster_up()) {
 			sleep(CONFIG_POLL_IN_SECS);
@@ -300,6 +321,45 @@ static void monitor(void)
 	}
 }
 
+/* Returns -1 if already running, 0 if not, 1 if unknown */
+static int is_already_running(void)
+{
+	int ret;
+
+	sem = sem_open(sem_name, O_CREAT, 0644, 1);
+	if (sem <= 0) {
+		fprintf(stderr, "%s\n", strerror(errno));
+		return 1;
+	}
+
+	ret = sem_trywait(sem);
+	if (ret) {
+		if (errno == EAGAIN)
+			return -1;
+		return 1;
+	}
+
+	sem_taken = 1;
+
+	return 0;
+}
+
+static int setup_signals(void)
+{
+	int ret = 0;
+
+	struct sigaction act = { .sa_handler = handler };
+
+	sigemptyset(&act.sa_mask);
+	ret = sigaction(SIGTERM, &act, NULL);
+	ret += sigaction(SIGINT, &act, NULL);
+	ret += sigaction(SIGHUP, &act, NULL);
+	ret += sigaction(SIGQUIT, &act, NULL);
+	ret += sigaction(SIGSEGV, &act, NULL);
+
+	return ret;
+}
+
 static void usage(void)
 {
 	fprintf(stderr, "usage: %s [-w percent] -[ivV]\n", progname);
@@ -320,6 +380,9 @@ int main(int argc, char **argv)
 	warn_threshold_percent = WARN_THRESHOLD_PERCENT;
 	verbose = 0;
 	cluster_name = NULL;
+	sem = NULL;
+	sem_taken = 0;
+	snprintf(sem_name, sizeof(sem_name), "/%s", progname);
 
 	while (1) {
 		c = getopt(argc, argv, "w:i?hvV");
@@ -352,6 +415,27 @@ int main(int argc, char **argv)
 	if (version)
 		show_version();
 
+	ret = setup_signals();
+	if (ret) {
+		fprintf(stderr, "Unable to set up signal handlers. %s. "
+			"Aborting.\n", strerror(errno));
+		goto bail;
+	}
+
+	ret = is_already_running();
+	switch (ret) {
+	case -1:
+		fprintf(stderr, "Another instance of %s is already running. "
+			"Aborting.\n", progname);
+		goto bail;
+	case 1:
+		fprintf(stderr, "Unable to determine if %s is already "
+			"running. Starting a new instance.\n", progname);
+	case 0:
+	default:
+		break;
+	}
+
 	if (!interactive) {
 		ret = daemon(0, verbose);
 		if (ret)
@@ -363,5 +447,6 @@ int main(int argc, char **argv)
 	monitor();
 	closelog();
 
+bail:
 	return 0;
 }
-- 
1.5.6.5




More information about the Ocfs2-tools-devel mailing list