[Cluster-devel] [PATCH 2/2] rgmanager: Block signals when dealing with dbus [RHEL6]

Lon Hohberger lhh at redhat.com
Wed Oct 19 03:26:10 UTC 2011


DBus calls seem to not retry in the event of signals; it
appears that occasionally this causes a double unref or
a segfault.  So, block signals when dealing with DBus in
order to prevent rgmanager from crashing.

Resolves: rhbz#741607

Signed-off-by: Lon Hohberger <lhh at redhat.com>
---
 rgmanager/src/daemons/update-dbus.c |   62 +++++++++++++++++++++++++++-------
 1 files changed, 49 insertions(+), 13 deletions(-)

diff --git a/rgmanager/src/daemons/update-dbus.c b/rgmanager/src/daemons/update-dbus.c
index 29ecaca..e706746 100644
--- a/rgmanager/src/daemons/update-dbus.c
+++ b/rgmanager/src/daemons/update-dbus.c
@@ -12,6 +12,7 @@
 #include <dbus/dbus.h>
 #include <liblogthread.h>
 #include <members.h>
+#include <signal.h>
 
 
 #define DBUS_RGM_NAME	"com.redhat.cluster.rgmanager"
@@ -28,6 +29,28 @@ static pthread_t th = 0;
 /* Set this to the desired value prior to calling rgm_dbus_init() */
 int rgm_dbus_notify = RGM_DBUS_DEFAULT;
 
+/*
+ * block the world when entering dbus critical sections so that
+ * if we get a signal while in dbus critical (exclusive of crash
+ * signals), we ignore it
+ */
+#define DBUS_ENTRY(set, old) \
+do { \
+	pthread_mutex_lock(&mu); \
+	sigfillset(&set); \
+	sigdelset(&set, SIGILL); \
+	sigdelset(&set, SIGSEGV); \
+	sigdelset(&set, SIGABRT); \
+	sigdelset(&set, SIGBUS); \
+	sigprocmask(SIG_SETMASK, &set, &old); \
+} while(0)
+
+#define DBUS_EXIT(old) \
+do { \
+	sigprocmask(SIG_SETMASK, &old, NULL); \
+	pthread_mutex_unlock(&mu); \
+} while(0)
+
 
 int 
 rgm_dbus_init(void)
@@ -35,13 +58,14 @@ rgm_dbus_init(void)
 {
 	DBusConnection *dbc = NULL;
 	DBusError err;
+	sigset_t set, old;
 
 	if (!rgm_dbus_notify)
 		return 0;
 
-	pthread_mutex_lock(&mu);
+	DBUS_ENTRY(set, old);
 	if (db) {
-		pthread_mutex_unlock(&mu);
+		DBUS_EXIT(old);
 		return 0;
 	}
 
@@ -53,7 +77,7 @@ rgm_dbus_init(void)
 			   "DBus Failed to initialize: dbus_bus_get: %s\n",
 			   err.message);
 		dbus_error_free(&err);
-		pthread_mutex_unlock(&mu);
+		DBUS_EXIT(old);
 		return -1;
 	}
 
@@ -63,7 +87,7 @@ rgm_dbus_init(void)
 
 	pthread_create(&th, NULL, _dbus_auto_flush, NULL);
 
-	pthread_mutex_unlock(&mu);
+	DBUS_EXIT(old);
 	logt_print(LOG_DEBUG, "DBus Notifications Initialized\n");
 	return 0;
 }
@@ -111,10 +135,11 @@ rgm_dbus_release(void)
 #ifdef DBUS
 {
 	int ret;
+	sigset_t set, old;
 
-	pthread_mutex_lock(&mu);
+	DBUS_ENTRY(set, old);
 	ret = _rgm_dbus_release();
-	pthread_mutex_unlock(&mu);
+	DBUS_EXIT(old);
 	return ret;
 }
 #else
@@ -131,6 +156,15 @@ rgm_dbus_release(void)
 static void *
 _dbus_auto_flush(void *arg)
 {
+	sigset_t set;
+
+	sigfillset(&set);
+	sigdelset(&set, SIGILL);
+	sigdelset(&set, SIGSEGV);
+	sigdelset(&set, SIGABRT);
+	sigdelset(&set, SIGBUS);
+	sigprocmask(SIG_SETMASK, &set, NULL);
+
 	/* DBus connection functions are thread safe */
 	while (dbus_connection_read_write(db, 500)) {
 		if (!th)
@@ -151,8 +185,9 @@ _rgm_dbus_notify(const char *svcname,
 {
 	DBusMessage *msg = NULL;
 	int ret = 0;
+	sigset_t set, old;
 
-	pthread_mutex_lock(&mu);
+	DBUS_ENTRY(set, old);
 
 	if (!db) {
 		goto out_unlock;
@@ -197,10 +232,10 @@ _rgm_dbus_notify(const char *svcname,
 	ret = 0;
 
 out_unlock:
-	pthread_mutex_unlock(&mu);
+	DBUS_EXIT(old);
 	if (msg)
 		dbus_message_unref(msg);
-out_free:
+
 	return ret;
 }
 
@@ -216,6 +251,7 @@ rgm_dbus_update(char *key, uint64_t view, void *data, uint32_t size)
 	cluster_member_list_t *m = NULL;
 	const char *owner;
 	const char *last;
+	sigset_t set, old;
 	int ret = 0;
 
 	if (!rgm_dbus_notify)
@@ -225,18 +261,18 @@ rgm_dbus_update(char *key, uint64_t view, void *data, uint32_t size)
 	if (size != (sizeof(*st)))
 		goto out_free;
 	
-	pthread_mutex_lock(&mu);
+	DBUS_ENTRY(set, old);
 	if (!db) {
-		pthread_mutex_unlock(&mu);
+		DBUS_EXIT(old);
 		goto out_free;
 	}
 	if (!th) {
 		/* Dispatch thread died. */
 		_rgm_dbus_release();
-		pthread_mutex_unlock(&mu);
+		DBUS_EXIT(old);
 		goto out_free;
 	}
-	pthread_mutex_unlock(&mu);
+	DBUS_EXIT(old);
 
 	st = (rg_state_t *)data;
 	swab_rg_state_t(st);
-- 
1.7.3.4




More information about the Cluster-devel mailing list