[asterisk-commits] rmudgett: branch group/CCSS r241413 - /team/group/CCSS/main/ccss.c

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Jan 19 17:45:12 CST 2010


Author: rmudgett
Date: Tue Jan 19 17:45:08 2010
New Revision: 241413

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=241413
Log:
Fix crash, reference leaks, and memory leaks.

*  Fixed crash caused by ast_cc_agent_status_response() not passing the
expected parameter.  Also cc_status_response() needed to free that
parameter.
*  Fixed reference leaks in ast_cc_monitor_status_request(),
ast_cc_monitor_stop_ringing(), and ast_cc_monitor_party_b_free().
*  Fixed many reference and memory leaks when ast_taskprocessor_push()
fails.

Modified:
    team/group/CCSS/main/ccss.c

Modified: team/group/CCSS/main/ccss.c
URL: http://svnview.digium.com/svn/asterisk/team/group/CCSS/main/ccss.c?view=diff&rev=241413&r1=241412&r2=241413
==============================================================================
--- team/group/CCSS/main/ccss.c (original)
+++ team/group/CCSS/main/ccss.c Tue Jan 19 17:45:08 2010
@@ -1097,9 +1097,10 @@
 	gtcd->monitor = cc_ref(monitor, "Keep reference until taskprocessor callback executes");
 	gtcd->new_state = ast_event_get_ie_uint(event, AST_EVENT_IE_STATE);
 
-	ast_taskprocessor_push(cc_core_taskprocessor, generic_monitor_devstate_tp_cb, gtcd);
-
-	return;
+	if (ast_taskprocessor_push(cc_core_taskprocessor, generic_monitor_devstate_tp_cb, gtcd)) {
+		cc_unref(gtcd->monitor, "Kill reference from generic_monitor_devstate_cb");
+		ast_free(gtcd);
+	}
 }
 
 int ast_cc_available_timer_expire(const void *data)
@@ -2065,9 +2066,13 @@
 {
 	struct ast_cc_agent *agent = userdata;
 	struct ast_str *str = ast_str_alloca(128);
+
+	/* We can't unsubscribe from device state events here because it causes a deadlock */
+	if (ast_taskprocessor_push(cc_core_taskprocessor, generic_agent_devstate_unsubscribe,
+		cc_ref(agent, "ref agent for device state unsubscription"))) {
+		cc_unref(agent, "Unref agent unsubscribing from devstate failed");
+	}
 	ast_str_set(&str, 0, "%s is no longer busy\n", agent->interface);
-	/* We can't unsubscribe from device state events here because it causes a deadlock */
-	ast_taskprocessor_push(cc_core_taskprocessor, generic_agent_devstate_unsubscribe, cc_ref(agent, "ref agent for device state unsubscription"));
 	ast_cc_agent_caller_available(agent->core_id, ast_str_buffer(str));
 }
 
@@ -2771,6 +2776,7 @@
 
 static int cc_request_state_change(enum cc_state state, const int core_id, const char *debug)
 {
+	int res;
 	struct cc_state_change_args *args = ast_calloc(1, sizeof(*args) +
 			(ast_strlen_zero(debug) ? 0 : strlen(debug)));
 
@@ -2782,7 +2788,11 @@
 	args->core_id = core_id;
 	strcpy(args->debug, debug);
 
-	return ast_taskprocessor_push(cc_core_taskprocessor, cc_do_state_change, args);
+	res = ast_taskprocessor_push(cc_core_taskprocessor, cc_do_state_change, args);
+	if (res) {
+		ast_free(args);
+	}
+	return res;
 }
 
 struct cc_recall_ds_data {
@@ -3041,9 +3051,16 @@
 	return cc_request_state_change(CC_ACTIVE, core_id, debug);
 }
 
-int ast_cc_monitor_callee_available(struct ast_cc_monitor *monitor) {
-	return ast_taskprocessor_push(cc_core_taskprocessor, cc_devstate_change,
-			cc_ref(monitor, "Bump reference count until cc_devstate_change executes"));
+int ast_cc_monitor_callee_available(struct ast_cc_monitor *monitor)
+{
+	int res;
+
+	res = ast_taskprocessor_push(cc_core_taskprocessor, cc_devstate_change,
+		cc_ref(monitor, "Bump reference count until cc_devstate_change executes"));
+	if (res) {
+		cc_unref(monitor, "Kill reference from ast_cc_monitor_callee_available");
+	}
+	return res;
 }
 
 int ast_cc_agent_caller_busy(int core_id, const char * debug)
@@ -3206,6 +3223,7 @@
 {
 	struct ast_cc_monitor *monitor = find_monitor(monitor_name, monitor_type);
 	struct cc_monitor_failure_data *failure_data;
+	int res;
 
 	if (!monitor) {
 		ast_log(LOG_WARNING, "Couldn't find a monitor with name %s and type %s\n", monitor_name, monitor_type);
@@ -3220,7 +3238,12 @@
 	failure_data->monitor = monitor; /* No need to ref since find_monitor already did that */
 	failure_data->core_id = core_id;
 
-	return ast_taskprocessor_push(cc_core_taskprocessor, cc_monitor_failed, failure_data);
+	res = ast_taskprocessor_push(cc_core_taskprocessor, cc_monitor_failed, failure_data);
+	if (res) {
+		cc_unref(monitor, "ast_taskprocessor_push failed, unref monitor that we found");
+		ast_free(failure_data);
+	}
+	return res;
 }
 
 static int cc_status_request(void *data)
@@ -3235,14 +3258,18 @@
 
 int ast_cc_monitor_status_request(int core_id)
 {
+	int res;
 	struct cc_core_instance *core_instance = find_cc_core_instance(core_id);
 
 	if (!core_instance) {
 		return -1;
 	}
 
-	return ast_taskprocessor_push(cc_core_taskprocessor, cc_status_request,
-			cc_ref(core_instance, "Ref core instance for status request callback"));
+	res = ast_taskprocessor_push(cc_core_taskprocessor, cc_status_request, core_instance);
+	if (res) {
+		cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed");
+	}
+	return res;
 }
 
 static int cc_stop_ringing(void *data)
@@ -3264,14 +3291,18 @@
 
 int ast_cc_monitor_stop_ringing(int core_id)
 {
+	int res;
 	struct cc_core_instance *core_instance = find_cc_core_instance(core_id);
 
 	if (!core_instance) {
 		return -1;
 	}
 
-	return ast_taskprocessor_push(cc_core_taskprocessor, cc_stop_ringing,
-			cc_ref(core_instance, "Ref core instance for stop ringing callback"));
+	res = ast_taskprocessor_push(cc_core_taskprocessor, cc_stop_ringing, core_instance);
+	if (res) {
+		cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed");
+	}
+	return res;
 }
 
 static int cc_party_b_free(void *data)
@@ -3288,19 +3319,23 @@
 
 int ast_cc_monitor_party_b_free(int core_id)
 {
+	int res;
 	struct cc_core_instance *core_instance = find_cc_core_instance(core_id);
 
 	if (!core_instance) {
 		return -1;
 	}
 
-	return ast_taskprocessor_push(cc_core_taskprocessor, cc_party_b_free,
-		cc_ref(core_instance, "Ref core instance for party B free callback"));
+	res = ast_taskprocessor_push(cc_core_taskprocessor, cc_party_b_free, core_instance);
+	if (res) {
+		cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed");
+	}
+	return res;
 }
 
 struct cc_status_response_args {
+	struct cc_core_instance *core_instance;
 	enum ast_device_state devstate;
-	struct cc_core_instance *core_instance;
 };
 
 static int cc_status_response(void *data)
@@ -3310,6 +3345,8 @@
 	enum ast_device_state devstate = args->devstate;
 	int res;
 
+	ast_free(args);
+
 	res = core_instance->monitor->callbacks->status_response(core_instance->monitor, core_instance->core_id, devstate);
 	cc_unref(core_instance, "Status response finished. Unref core instance");
 	return res;
@@ -3317,14 +3354,35 @@
 
 int ast_cc_agent_status_response(int core_id, enum ast_device_state devstate)
 {
-	struct cc_core_instance *core_instance = find_cc_core_instance(core_id);
-
-	if (!core_instance || !core_instance->monitor) {
-		return -1;
-	}
-
-	return ast_taskprocessor_push(cc_core_taskprocessor, cc_status_response,
-			cc_ref(core_instance, "Ref core instance for status response callback"));
+	struct cc_status_response_args *args;
+	struct cc_core_instance *core_instance;
+	int res;
+
+	args = ast_calloc(1, sizeof(*args));
+	if (!args) {
+		return -1;
+	}
+
+	core_instance = find_cc_core_instance(core_id);
+	if (!core_instance) {
+		ast_free(args);
+		return -1;
+	}
+	if (!core_instance->monitor) {
+		cc_unref(core_instance, "Unref core instance for status response.  It does not have a monitor");
+		ast_free(args);
+		return -1;
+	}
+
+	args->core_instance = core_instance;
+	args->devstate = devstate;
+
+	res = ast_taskprocessor_push(cc_core_taskprocessor, cc_status_response, args);
+	if (res) {
+		cc_unref(core_instance, "Unref core instance. ast_taskprocessor_push failed");
+		ast_free(args);
+	}
+	return res;
 }
 
 static int cc_build_payload(struct ast_channel *chan, struct ast_cc_config_params *cc_params,
@@ -3647,8 +3705,16 @@
 	}
 
 	cli_fd = ast_malloc(sizeof(*cli_fd));
+	if (!cli_fd) {
+		return CLI_FAILURE;
+	}
+
 	*cli_fd = a->fd;
-	ast_taskprocessor_push(cc_core_taskprocessor, cc_cli_output_status, cli_fd);
+
+	if (ast_taskprocessor_push(cc_core_taskprocessor, cc_cli_output_status, cli_fd)) {
+		ast_free(cli_fd);
+		return CLI_FAILURE;
+	}
 	return CLI_SUCCESS;
 }
 




More information about the asterisk-commits mailing list