Просмотр исходного кода

Only call qb_ipcc_disconnect when the instance is fully dereferenced.

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.

Reviewed-by: Fabio M. Di Nitto <fdinitto@redhat.com>
Signed-off-by: Angus Salkeld <asalkeld@redhat.com>
Angus Salkeld 14 лет назад
Родитель
Сommit
acad48bf38
5 измененных файлов с 91 добавлено и 17 удалено
  1. 17 3
      lib/cfg.c
  2. 23 2
      lib/cmap.c
  3. 17 3
      lib/cpg.c
  4. 17 5
      lib/quorum.c
  5. 17 4
      lib/votequorum.c

+ 17 - 3
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);

+ 23 - 2
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

+ 17 - 3
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
 		 */

+ 17 - 5
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);

+ 17 - 4
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);