[asterisk-commits] mmichelson: branch group/CCSS_Monitor_Restructure r242033 - /team/group/CCSS_...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Thu Jan 21 13:02:10 CST 2010
Author: mmichelson
Date: Thu Jan 21 13:02:06 2010
New Revision: 242033
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=242033
Log:
Add more places to call the monitor-less destructor.
Modified:
team/group/CCSS_Monitor_Restructure/main/ccss.c
Modified: team/group/CCSS_Monitor_Restructure/main/ccss.c
URL: http://svnview.digium.com/svn/asterisk/team/group/CCSS_Monitor_Restructure/main/ccss.c?view=diff&rev=242033&r1=242032&r2=242033
==============================================================================
--- team/group/CCSS_Monitor_Restructure/main/ccss.c (original)
+++ team/group/CCSS_Monitor_Restructure/main/ccss.c Thu Jan 21 13:02:06 2010
@@ -1582,6 +1582,29 @@
char dialable_name[AST_CHANNEL_NAME];
};
+/*!
+ * \internal
+ * \brief Call a monitor's destructor before the monitor has been allocated
+ * \since 1.8
+ *
+ * \param monitor_type The type of monitor callbacks to use when calling the destructor
+ * \param private_data Data allocated by a channel driver that must be freed
+ *
+ * \details
+ * I'll admit, this is a bit evil.
+ *
+ * When a channel driver determines that it can offer a call completion service to
+ * a caller, it is very likely that the channel driver will need to allocate some
+ * data so that when the time comes to request CC, the channel driver will have the
+ * necessary data at hand.
+ *
+ * The problem is that there are many places where failures may occur before the monitor
+ * has been properly allocated and had its callbacks assigned to it. If one of these
+ * failures should occur, then we still need to let the channel driver know that it
+ * must destroy the data that it allocated.
+ *
+ * \return Nothing
+ */
static void call_destructor_with_no_monitor(const char * const monitor_type, void *private_data)
{
const struct ast_cc_monitor_callbacks *monitor_callbacks = find_monitor_callbacks(monitor_type);
@@ -1729,7 +1752,7 @@
core_instance = find_cc_core_instance(cc_interfaces->core_id);
if (!core_instance) {
core_instance = cc_core_init_instance(inbound, cc_interfaces->interface_tree,
- cc_interfaces->core_id);
+ cc_interfaces->core_id, cc_data);
if (!core_instance) {
cc_interfaces->ignore = 1;
ast_channel_unlock(inbound);
@@ -2217,57 +2240,6 @@
ast_free(agent_pvt);
}
-
-/*!
- * \internal
- * \brief Walk the CC interface tree and destroy monitor instances.
- * \since 1.8
- *
- * \param interface_tree Interface tree to kill any monitor instances.
- * \param core_id core_id of the CC transaction.
- *
- * \details
- * I'll admit, this is a bit evil.
- *
- * Picture the following scenario: A called party can support CC, so
- * it queues an AST_CONTROL_CC frame. Now, the channel driver will likely
- * need to retain some information about the call. This information is expected
- * to be destroyed when the monitor's destructor is called.
- * However, consider that the caller never requests CC (i.e.
- * the offer timer expires). In this case, the monitor never gets created,
- * and so the retained data in the called party's channel driver is leaked.
- *
- * The way that we deal with this scenario is to traverse the list of dialed
- * devices in the agent's interface_tree. Each device will have its monitor instance
- * destructor function called directly, even though no monitor was ever created.
- *
- * \return Nothing
- */
-static void kill_interface_tree_monitors(struct ast_cc_interface_tree *interface_tree, const int core_id)
-{
- const struct ast_cc_monitor_callbacks *monitor_callbacks;
- struct cc_monitor *monitor_iter;
-
- /* Locking is necessary here since a channel thread could possibly be mucking
- * with this list while we try to traverse it
- */
- AST_DLLIST_LOCK(interface_tree);
- AST_DLLIST_TRAVERSE(interface_tree, monitor_iter, next) {
- if (monitor_iter->interface->monitor_class == AST_CC_DEVICE_MONITOR) {
- monitor_callbacks =
- find_monitor_callbacks(monitor_iter->interface->monitor_type);
- if (!monitor_callbacks) {
- ast_log(LOG_WARNING,
- "We may have a memory leak here. Couldn't find callbacks for monitor type %s\n",
- monitor_iter->interface->monitor_type);
- continue;
- }
- monitor_callbacks->instance_destructor(core_id);
- }
- }
- AST_DLLIST_UNLOCK(interface_tree);
-}
-
static void cc_core_instance_destructor(void *data)
{
struct cc_core_instance *core_instance = data;
@@ -2281,7 +2253,7 @@
}
static struct cc_core_instance *cc_core_init_instance(struct ast_channel *caller_chan,
- struct ast_cc_interface_tree *called_tree, const int core_id)
+ struct ast_cc_interface_tree *called_tree, const int core_id, struct ast_control_cc_payload *cc_data)
{
char caller[AST_CHANNEL_NAME];
struct cc_core_instance *core_instance;
@@ -2301,33 +2273,33 @@
if (!cc_params) {
ast_log_dynamic_level(cc_logger_level, "Could not get CC parameters for %s\n",
caller);
- kill_interface_tree_monitors(called_tree, core_id);
+ call_destructor_with_no_monitor(cc_data->monitor_type, cc_data->private_data);
return NULL;
}
agent_count = count_agents(caller, recall_core_id);
if (agent_count >= ast_get_cc_max_agents(cc_params)) {
ast_log_dynamic_level(cc_logger_level, "Caller %s already has the maximum number of agents configured\n", caller);
- kill_interface_tree_monitors(called_tree, core_id);
+ call_destructor_with_no_monitor(cc_data->monitor_type, cc_data->private_data);
return NULL;
}
/* Generic agents can only have a single outstanding CC request per caller. */
if (agent_count > 0 && ast_get_cc_agent_policy(cc_params) == AST_CC_AGENT_GENERIC) {
ast_log_dynamic_level(cc_logger_level, "Generic agents can only have a single outstanding request\n");
- kill_interface_tree_monitors(called_tree, core_id);
+ call_destructor_with_no_monitor(cc_data->monitor_type, cc_data->private_data);
return NULL;
}
/* Next, we need to create the core instance for this call */
if (!(core_instance = ao2_t_alloc(sizeof(*core_instance), cc_core_instance_destructor, "Creating core instance for CC"))) {
- kill_interface_tree_monitors(called_tree, core_id);
+ call_destructor_with_no_monitor(cc_data->monitor_type, cc_data->private_data);
return NULL;
}
core_instance->core_id = core_id;
if (!(core_instance->agent = cc_agent_init(caller_chan, caller, core_instance->core_id, called_tree))) {
cc_unref(core_instance, "Couldn't allocate agent, unref core_instance");
- kill_interface_tree_monitors(called_tree, core_id);
+ call_destructor_with_no_monitor(cc_data->monitor_type, cc_data->private_data);
return NULL;
}
More information about the asterisk-commits
mailing list