[PATCH] Only call qb_ipcc_disconnect when the instance is fully dereferenced.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Sometimes calling xyz_finilize() within a dispatch would
cause a crash because the qb_ipcc_disconnect actually
disconnects immediatly and frees it't memory. whereas
the corosync structure is reference counted. So this
makes use of the reference counting to only call
qb_ipcc_disconnect when it is fully dereferenced.

Signed-off-by: Angus Salkeld <asalkeld@xxxxxxxxxx>
---
 lib/cfg.c        |   20 +++++++++++++++++---
 lib/cmap.c       |   25 +++++++++++++++++++++++--
 lib/cpg.c        |   20 +++++++++++++++++---
 lib/quorum.c     |   22 +++++++++++++++++-----
 lib/votequorum.c |   21 +++++++++++++++++----
 5 files changed, 91 insertions(+), 17 deletions(-)

diff --git a/lib/cfg.c b/lib/cfg.c
index 34b8ea4..248df4d 100644
--- a/lib/cfg.c
+++ b/lib/cfg.c
@@ -72,7 +72,9 @@ struct cfg_inst {
 /*
  * All instances in one database
  */
-DECLARE_HDB_DATABASE (cfg_hdb,NULL);
+static void cfg_inst_free (void *inst);
+
+DECLARE_HDB_DATABASE (cfg_hdb, cfg_inst_free);
 
 /*
  * Implementation
@@ -96,6 +98,7 @@ corosync_cfg_initialize (
 		goto error_destroy;
 	}
 
+	cfg_inst->finalize = 0;
 	cfg_inst->c = qb_ipcc_connect ("cfg", IPC_REQUEST_SIZE);
 	if (cfg_inst->c == NULL) {
 		error = qb_to_cs_error(-errno);
@@ -218,6 +221,13 @@ corosync_cfg_dispatch (
 			goto error_nounlock;
 			break;
 		}
+		if (cfg_inst->finalize) {
+			/*
+			 * If the finalize has been called then get out of the dispatch.
+			 */
+			error = CS_ERR_BAD_HANDLE;
+			goto error_put;
+		}
 
 		/*
 		 * Determine if more messages should be processed
@@ -233,6 +243,12 @@ error_nounlock:
 	return (error);
 }
 
+static void cfg_inst_free (void *inst)
+{
+	struct cfg_inst *cfg_inst = (struct cfg_inst *)inst;
+	qb_ipcc_disconnect(cfg_inst->c);
+}
+
 cs_error_t
 corosync_cfg_finalize (
 	corosync_cfg_handle_t cfg_handle)
@@ -255,8 +271,6 @@ corosync_cfg_finalize (
 
 	cfg_inst->finalize = 1;
 
-	qb_ipcc_disconnect (cfg_inst->c);
-
 	(void)hdb_handle_destroy (&cfg_hdb, cfg_handle);
 
 	(void)hdb_handle_put (&cfg_hdb, cfg_handle);
diff --git a/lib/cmap.c b/lib/cmap.c
index 1a58541..bfe7d6e 100644
--- a/lib/cmap.c
+++ b/lib/cmap.c
@@ -54,6 +54,7 @@
 #include <stdio.h>
 
 struct cmap_inst {
+	int finalize;
 	qb_ipcc_connection_t *c;
 	const void *context;
 };
@@ -65,7 +66,9 @@ struct cmap_track_inst {
 	cmap_track_handle_t track_handle;
 };
 
-DECLARE_HDB_DATABASE(cmap_handle_t_db,NULL);
+static void cmap_inst_free (void *inst);
+
+DECLARE_HDB_DATABASE(cmap_handle_t_db, cmap_inst_free);
 DECLARE_HDB_DATABASE(cmap_track_handle_t_db,NULL);
 
 /*
@@ -99,6 +102,7 @@ cs_error_t cmap_initialize (cmap_handle_t *handle)
 	}
 
 	error = CS_OK;
+	cmap_inst->finalize = 0;
 	cmap_inst->c = qb_ipcc_connect("cmap", IPC_REQUEST_SIZE);
 	if (cmap_inst->c == NULL) {
 		error = qb_to_cs_error(-errno);
@@ -117,6 +121,12 @@ error_no_destroy:
 	return (error);
 }
 
+static void cmap_inst_free (void *inst)
+{
+	struct cmap_inst *cmap_inst = (struct cmap_inst *)inst;
+	qb_ipcc_disconnect(cmap_inst->c);
+}
+
 cs_error_t cmap_finalize(cmap_handle_t handle)
 {
 	struct cmap_inst *cmap_inst;
@@ -129,7 +139,11 @@ cs_error_t cmap_finalize(cmap_handle_t handle)
 		return (error);
 	}
 
-	qb_ipcc_disconnect(cmap_inst->c);
+	if (cmap_inst->finalize) {
+		(void)hdb_handle_put (&cmap_handle_t_db, handle);
+		return (CS_ERR_BAD_HANDLE);
+	}
+	cmap_inst->finalize = 1;
 
 	/*
 	 * Destroy all track instances for given connection
@@ -270,6 +284,13 @@ cs_error_t cmap_dispatch (
 			goto error_put;
 			break;
 		}
+		if (cmap_inst->finalize) {
+			/*
+			 * If the finalize has been called then get out of the dispatch.
+			 */
+			error = CS_ERR_BAD_HANDLE;
+			goto error_put;
+		}
 
 		/*
 		 * Determine if more messages should be processed
diff --git a/lib/cpg.c b/lib/cpg.c
index 700303f..0c9fa1a 100644
--- a/lib/cpg.c
+++ b/lib/cpg.c
@@ -73,8 +73,9 @@ struct cpg_inst {
 	};
 	struct list_head iteration_list_head;
 };
+static void cpg_inst_free (void *inst);
 
-DECLARE_HDB_DATABASE(cpg_handle_t_db,NULL);
+DECLARE_HDB_DATABASE(cpg_handle_t_db, cpg_inst_free);
 
 struct cpg_iteration_instance_t {
 	cpg_iteration_handle_t cpg_iteration_handle;
@@ -108,6 +109,12 @@ static void cpg_iteration_instance_finalize (struct cpg_iteration_instance_t *cp
 	hdb_handle_destroy (&cpg_iteration_handle_t_db, cpg_iteration_instance->cpg_iteration_handle);
 }
 
+static void cpg_inst_free (void *inst)
+{
+	struct cpg_inst *cpg_inst = (struct cpg_inst *)inst;
+	qb_ipcc_disconnect(cpg_inst->c);
+}
+
 static void cpg_inst_finalize (struct cpg_inst *cpg_inst, hdb_handle_t handle)
 {
 	struct list_head *iter, *iter_next;
@@ -248,8 +255,6 @@ cs_error_t cpg_finalize (
 		&res_lib_cpg_finalize,
 		sizeof (struct res_lib_cpg_finalize));
 
-	qb_ipcc_disconnect(cpg_inst->c);
-
 	cpg_inst_finalize (cpg_inst, handle);
 	hdb_handle_put (&cpg_handle_t_db, handle);
 
@@ -475,6 +480,15 @@ cs_error_t cpg_dispatch (
 			break; /* case CPG_MODEL_V1 */
 		} /* - switch (cpg_inst_copy.model_data.model) */
 
+		if (cpg_inst_copy.finalize || cpg_inst->finalize) {
+			/*
+			 * If the finalize has been called then get out of the dispatch.
+			 */
+			cpg_inst->finalize = 1;
+			error = CS_ERR_BAD_HANDLE;
+			goto error_put;
+		}
+
 		/*
 		 * Determine if more messages should be processed
 		 */
diff --git a/lib/quorum.c b/lib/quorum.c
index 1ee2f06..eb53b7f 100644
--- a/lib/quorum.c
+++ b/lib/quorum.c
@@ -61,7 +61,9 @@ struct quorum_inst {
 	quorum_callbacks_t callbacks;
 };
 
-DECLARE_HDB_DATABASE(quorum_handle_t_db,NULL);
+static void quorum_inst_free (void *inst);
+
+DECLARE_HDB_DATABASE(quorum_handle_t_db, quorum_inst_free);
 
 cs_error_t quorum_initialize (
 	quorum_handle_t *handle,
@@ -85,6 +87,7 @@ cs_error_t quorum_initialize (
 	}
 
 	error = CS_OK;
+	quorum_inst->finalize = 0;
 	quorum_inst->c = qb_ipcc_connect ("quorum", IPC_REQUEST_SIZE);
 	if (quorum_inst->c == NULL) {
 		error = qb_to_cs_error(-errno);
@@ -129,6 +132,12 @@ error_no_destroy:
 	return (error);
 }
 
+static void quorum_inst_free (void *inst)
+{
+	struct quorum_inst *quorum_inst = (struct quorum_inst *)inst;
+	qb_ipcc_disconnect(quorum_inst->c);
+}
+
 cs_error_t quorum_finalize (
 	quorum_handle_t handle)
 {
@@ -150,8 +159,6 @@ cs_error_t quorum_finalize (
 
 	quorum_inst->finalize = 1;
 
-	qb_ipcc_disconnect (quorum_inst->c);
-
 	(void)hdb_handle_destroy (&quorum_handle_t_db, handle);
 
 	(void)hdb_handle_put (&quorum_handle_t_db, handle);
@@ -433,6 +440,13 @@ cs_error_t quorum_dispatch (
 			goto error_put;
 			break;
 		}
+		if (quorum_inst->finalize) {
+			/*
+			 * If the finalize has been called then get out of the dispatch.
+			 */
+			error = CS_ERR_BAD_HANDLE;
+			goto error_put;
+		}
 
 		/*
 		 * Determine if more messages should be processed
@@ -442,8 +456,6 @@ cs_error_t quorum_dispatch (
 		}
 	} while (cont);
 
-	goto error_put;
-
 error_put:
 	(void)hdb_handle_put (&quorum_handle_t_db, handle);
 	return (error);
diff --git a/lib/votequorum.c b/lib/votequorum.c
index 6240f99..e2b578f 100644
--- a/lib/votequorum.c
+++ b/lib/votequorum.c
@@ -64,7 +64,9 @@ struct votequorum_inst {
 	votequorum_callbacks_t callbacks;
 };
 
-DECLARE_HDB_DATABASE(votequorum_handle_t_db,NULL);
+static void votequorum_inst_free (void *inst);
+
+DECLARE_HDB_DATABASE(votequorum_handle_t_db, votequorum_inst_free);
 
 cs_error_t votequorum_initialize (
 	votequorum_handle_t *handle,
@@ -83,6 +85,7 @@ cs_error_t votequorum_initialize (
 		goto error_destroy;
 	}
 
+	votequorum_inst->finalize = 0;
 	votequorum_inst->c = qb_ipcc_connect ("votequorum", IPC_REQUEST_SIZE);
 	if (votequorum_inst->c == NULL) {
 		error = qb_to_cs_error(-errno);
@@ -106,6 +109,12 @@ error_no_destroy:
 	return (error);
 }
 
+static void votequorum_inst_free (void *inst)
+{
+	struct votequorum_inst *vq_inst = (struct votequorum_inst *)inst;
+	qb_ipcc_disconnect(vq_inst->c);
+}
+
 cs_error_t votequorum_finalize (
 	votequorum_handle_t handle)
 {
@@ -127,8 +136,6 @@ cs_error_t votequorum_finalize (
 
 	votequorum_inst->finalize = 1;
 
-	qb_ipcc_disconnect (votequorum_inst->c);
-
 	hdb_handle_destroy (&votequorum_handle_t_db, handle);
 
 	hdb_handle_put (&votequorum_handle_t_db, handle);
@@ -521,6 +528,13 @@ cs_error_t votequorum_dispatch (
 			goto error_put;
 			break;
 		}
+		if (votequorum_inst->finalize) {
+			/*
+			 * If the finalize has been called then get out of the dispatch.
+			 */
+			error = CS_ERR_BAD_HANDLE;
+			goto error_put;
+		}
 
 		/*
 		 * Determine if more messages should be processed
@@ -530,7 +544,6 @@ cs_error_t votequorum_dispatch (
 		}
 	} while (cont);
 
-	goto error_put;
 
 error_put:
 	hdb_handle_put (&votequorum_handle_t_db, handle);
-- 
1.7.9.3

_______________________________________________
discuss mailing list
discuss@xxxxxxxxxxxx
http://lists.corosync.org/mailman/listinfo/discuss


[Index of Archives]     [Linux Clusters]     [Corosync Project]     [Linux USB Devel]     [Linux Audio Users]     [Photo]     [Yosemite News]    [Yosemite Photos]    [Linux Kernel]     [Linux SCSI]     [X.Org]

  Powered by Linux