[svn-commits] rmudgett: branch group/CCSS r241413 - /team/group/CCSS/main/ccss.c
SVN commits to the Digium repositories
svn-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 svn-commits
mailing list