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

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

 



Laaaaaaadiesssss and gentlement... WE HAVE A WINNER!!!


On 04/03/2012 01:57 AM, Angus Salkeld wrote:
> 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);

_______________________________________________
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