diff --git a/apps/app_dial.c b/apps/app_dial.c index d76a0cf6aa..b43674088a 100644 --- a/apps/app_dial.c +++ b/apps/app_dial.c @@ -2395,14 +2395,6 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast peer = wait_for_answer(chan, outgoing, &to, peerflags, opt_args, &pa, &num, &result, dtmf_progress, ignore_cc, &forced_clid, &stored_clid); - /* The ast_channel_datastore_remove() function could fail here if the - * datastore was moved to another channel during a masquerade. If this is - * the case, don't free the datastore here because later, when the channel - * to which the datastore was moved hangs up, it will attempt to free this - * datastore again, causing a crash - */ - if (!ast_channel_datastore_remove(chan, datastore)) - ast_datastore_free(datastore); if (!peer) { if (result) { res = result; diff --git a/apps/app_queue.c b/apps/app_queue.c index 5c348b7523..465356e610 100644 --- a/apps/app_queue.c +++ b/apps/app_queue.c @@ -4567,17 +4567,6 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce if (need_weight) ao2_unlock(queues); lpeer = wait_for_answer(qe, outgoing, &to, &digit, numbusies, ast_test_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT), forwardsallowed, update_connectedline); - /* The ast_channel_datastore_remove() function could fail here if the - * datastore was moved to another channel during a masquerade. If this is - * the case, don't free the datastore here because later, when the channel - * to which the datastore was moved hangs up, it will attempt to free this - * datastore again, causing a crash - */ - ast_channel_lock(qe->chan); - if (datastore && !ast_channel_datastore_remove(qe->chan, datastore)) { - ast_datastore_free(datastore); - } - ast_channel_unlock(qe->chan); ao2_lock(qe->parent); if (qe->parent->strategy == QUEUE_STRATEGY_RRMEMORY || qe->parent->strategy == QUEUE_STRATEGY_RRORDERED) { store_next_rr(qe, outgoing); diff --git a/main/features.c b/main/features.c index cf08c68aba..f779623475 100644 --- a/main/features.c +++ b/main/features.c @@ -3416,6 +3416,22 @@ static void add_features_datastores(struct ast_channel *caller, struct ast_chann return; } +static void clear_dialed_interfaces(struct ast_channel *chan) +{ + struct ast_datastore *di_datastore; + + ast_channel_lock(chan); + if ((di_datastore = ast_channel_datastore_find(chan, &dialed_interface_info, NULL))) { + if (option_debug) { + ast_log(LOG_DEBUG, "Removing dialed interfaces datastore on %s since we're bridging\n", chan->name); + } + if (!ast_channel_datastore_remove(chan, di_datastore)) { + ast_datastore_free(di_datastore); + } + } + ast_channel_unlock(chan); +} + /*! * \brief bridge the call and set CDR * \param chan,peer,config @@ -3601,6 +3617,13 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast ast_clear_flag(bridge_cdr, AST_CDR_FLAG_DIALED); } ast_cel_report_event(chan, AST_CEL_BRIDGE_START, NULL, NULL, NULL); + + /* If we are bridging a call, stop worrying about forwarding loops. We presume that if + * a call is being bridged, that the humans in charge know what they're doing. If they + * don't, well, what can we do about that? */ + clear_dialed_interfaces(chan); + clear_dialed_interfaces(peer); + for (;;) { struct ast_channel *other; /* used later */