Fix potential bridge hook resource leak if the hook install fails.

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@392335 65c4cc65-6c06-0410-ace0-fbb531ad65f3
changes/78/78/1
Richard Mudgett 12 years ago
parent 33eb15a242
commit cd40e179a9

@ -2161,8 +2161,10 @@ int conf_set_menu_to_user(const char *menu_name, struct confbridge_user *user)
ao2_ref(menu, +1); ao2_ref(menu, +1);
pvt->menu = menu; pvt->menu = menu;
ast_bridge_dtmf_hook(&user->features, pvt->menu_entry.dtmf, menu_hook_callback, if (ast_bridge_dtmf_hook(&user->features, pvt->menu_entry.dtmf,
pvt, menu_hook_destroy, 0); menu_hook_callback, pvt, menu_hook_destroy, 0)) {
menu_hook_destroy(pvt);
}
} }
ao2_unlock(menu); ao2_unlock(menu);

@ -390,7 +390,7 @@ int ast_bridge_interval_unregister(enum ast_bridge_builtin_interval interval);
* \param remove_flags Dictates what situations the hook should be removed. * \param remove_flags Dictates what situations the hook should be removed.
* *
* \retval 0 on success * \retval 0 on success
* \retval -1 on failure * \retval -1 on failure (The caller must cleanup any hook_pvt resources.)
* *
* Example usage: * Example usage:
* *
@ -420,7 +420,7 @@ int ast_bridge_join_hook(struct ast_bridge_features *features,
* \param remove_flags Dictates what situations the hook should be removed. * \param remove_flags Dictates what situations the hook should be removed.
* *
* \retval 0 on success * \retval 0 on success
* \retval -1 on failure * \retval -1 on failure (The caller must cleanup any hook_pvt resources.)
* *
* Example usage: * Example usage:
* *
@ -450,7 +450,7 @@ int ast_bridge_leave_hook(struct ast_bridge_features *features,
* \param remove_flags Dictates what situations the hook should be removed. * \param remove_flags Dictates what situations the hook should be removed.
* *
* \retval 0 on success * \retval 0 on success
* \retval -1 on failure * \retval -1 on failure (The caller must cleanup any hook_pvt resources.)
* *
* Example usage: * Example usage:
* *
@ -481,7 +481,7 @@ int ast_bridge_hangup_hook(struct ast_bridge_features *features,
* \param remove_flags Dictates what situations the hook should be removed. * \param remove_flags Dictates what situations the hook should be removed.
* *
* \retval 0 on success * \retval 0 on success
* \retval -1 on failure * \retval -1 on failure (The caller must cleanup any hook_pvt resources.)
* *
* Example usage: * Example usage:
* *
@ -503,7 +503,7 @@ int ast_bridge_dtmf_hook(struct ast_bridge_features *features,
enum ast_bridge_hook_remove_flags remove_flags); enum ast_bridge_hook_remove_flags remove_flags);
/*! /*!
* \brief attach an interval hook to a bridge features structure * \brief Attach an interval hook to a bridge features structure
* *
* \param features Bridge features structure * \param features Bridge features structure
* \param interval The interval that the hook should execute at in milliseconds * \param interval The interval that the hook should execute at in milliseconds
@ -513,7 +513,7 @@ int ast_bridge_dtmf_hook(struct ast_bridge_features *features,
* \param remove_flags Dictates what situations the hook should be removed. * \param remove_flags Dictates what situations the hook should be removed.
* *
* \retval 0 on success * \retval 0 on success
* \retval -1 on failure * \retval -1 on failure (The caller must cleanup any hook_pvt resources.)
* *
* \code * \code
* struct ast_bridge_features features; * struct ast_bridge_features features;

@ -4893,6 +4893,15 @@ int ast_bridge_dtmf_hook(struct ast_bridge_features *features,
/* Once done we put it in the container. */ /* Once done we put it in the container. */
res = ao2_link(features->dtmf_hooks, hook) ? 0 : -1; res = ao2_link(features->dtmf_hooks, hook) ? 0 : -1;
if (res) {
/*
* Could not link the hook into the container.
*
* Remove the hook_pvt destructor call from the hook since we
* are returning failure to install the hook.
*/
hook->destructor = NULL;
}
ao2_ref(hook, -1); ao2_ref(hook, -1);
return res; return res;
@ -4916,6 +4925,15 @@ int ast_bridge_hangup_hook(struct ast_bridge_features *features,
/* Once done we put it in the container. */ /* Once done we put it in the container. */
res = ao2_link(features->hangup_hooks, hook) ? 0 : -1; res = ao2_link(features->hangup_hooks, hook) ? 0 : -1;
if (res) {
/*
* Could not link the hook into the container.
*
* Remove the hook_pvt destructor call from the hook since we
* are returning failure to install the hook.
*/
hook->destructor = NULL;
}
ao2_ref(hook, -1); ao2_ref(hook, -1);
return res; return res;
@ -4939,6 +4957,15 @@ int ast_bridge_join_hook(struct ast_bridge_features *features,
/* Once done we put it in the container. */ /* Once done we put it in the container. */
res = ao2_link(features->join_hooks, hook) ? 0 : -1; res = ao2_link(features->join_hooks, hook) ? 0 : -1;
if (res) {
/*
* Could not link the hook into the container.
*
* Remove the hook_pvt destructor call from the hook since we
* are returning failure to install the hook.
*/
hook->destructor = NULL;
}
ao2_ref(hook, -1); ao2_ref(hook, -1);
return res; return res;
@ -4962,6 +4989,15 @@ int ast_bridge_leave_hook(struct ast_bridge_features *features,
/* Once done we put it in the container. */ /* Once done we put it in the container. */
res = ao2_link(features->leave_hooks, hook) ? 0 : -1; res = ao2_link(features->leave_hooks, hook) ? 0 : -1;
if (res) {
/*
* Could not link the hook into the container.
*
* Remove the hook_pvt destructor call from the hook since we
* are returning failure to install the hook.
*/
hook->destructor = NULL;
}
ao2_ref(hook, -1); ao2_ref(hook, -1);
return res; return res;
@ -5013,11 +5049,17 @@ int ast_bridge_interval_hook(struct ast_bridge_features *features,
hook, hook->parms.timer.interval, features); hook, hook->parms.timer.interval, features);
ast_heap_wrlock(features->interval_hooks); ast_heap_wrlock(features->interval_hooks);
res = ast_heap_push(features->interval_hooks, hook); res = ast_heap_push(features->interval_hooks, hook);
ast_heap_unlock(features->interval_hooks);
if (res) { if (res) {
/* Could not push the hook onto the heap. */ /*
* Could not push the hook into the heap
*
* Remove the hook_pvt destructor call from the hook since we
* are returning failure to install the hook.
*/
hook->destructor = NULL;
ao2_ref(hook, -1); ao2_ref(hook, -1);
} }
ast_heap_unlock(features->interval_hooks);
return res ? -1 : 0; return res ? -1 : 0;
} }

@ -3415,6 +3415,7 @@ static int dynamic_dtmf_hook_add(struct ast_bridge_features *features, unsigned
size_t len_moh = ast_strlen_zero(moh_class) ? 0 : strlen(moh_class) + 1; size_t len_moh = ast_strlen_zero(moh_class) ? 0 : strlen(moh_class) + 1;
size_t len_feature = strlen(feature_name) + 1; size_t len_feature = strlen(feature_name) + 1;
size_t len_data = sizeof(*hook_data) + len_name + len_args + len_moh + len_feature; size_t len_data = sizeof(*hook_data) + len_name + len_args + len_moh + len_feature;
int res;
/* Fill in application run hook data. */ /* Fill in application run hook data. */
hook_data = ast_malloc(len_data); hook_data = ast_malloc(len_data);
@ -3434,8 +3435,12 @@ static int dynamic_dtmf_hook_add(struct ast_bridge_features *features, unsigned
} }
strcpy(&hook_data->app_name[hook_data->feature_offset], feature_name);/* Safe */ strcpy(&hook_data->app_name[hook_data->feature_offset], feature_name);/* Safe */
return ast_bridge_dtmf_hook(features, dtmf, dynamic_dtmf_hook_trip, hook_data, res = ast_bridge_dtmf_hook(features, dtmf, dynamic_dtmf_hook_trip, hook_data,
ast_free_ptr, AST_BRIDGE_HOOK_REMOVE_ON_PULL); ast_free_ptr, AST_BRIDGE_HOOK_REMOVE_ON_PULL);
if (res) {
ast_free(hook_data);
}
return res;
} }
static int setup_dynamic_feature(void *obj, void *arg, void *data, int flags) static int setup_dynamic_feature(void *obj, void *arg, void *data, int flags)

@ -542,6 +542,7 @@ void parking_set_duration(struct ast_bridge_features *features, struct parked_us
if (ast_bridge_interval_hook(features, time_limit, if (ast_bridge_interval_hook(features, time_limit,
parking_duration_callback, user, parking_duration_cb_destroyer, AST_BRIDGE_HOOK_REMOVE_ON_PULL)) { parking_duration_callback, user, parking_duration_cb_destroyer, AST_BRIDGE_HOOK_REMOVE_ON_PULL)) {
ast_log(LOG_ERROR, "Failed to apply duration limits to the parking call.\n"); ast_log(LOG_ERROR, "Failed to apply duration limits to the parking call.\n");
ao2_ref(user, -1);
} }
} }

Loading…
Cancel
Save