diff --git a/apps/app_dial.c b/apps/app_dial.c index 3f0c67082a..fec1c9b729 100644 --- a/apps/app_dial.c +++ b/apps/app_dial.c @@ -1453,14 +1453,6 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags time(&start_time); peer = wait_for_answer(chan, outgoing, &to, peerflags, &sentringing, status, sizeof(status), numbusy, numnochan, numcongestion, ast_test_flag(&opts, OPT_PRIORITY_JUMP), &result); - /* 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_channel_datastore_free(datastore); if (!peer) { if (result) { res = result; diff --git a/apps/app_queue.c b/apps/app_queue.c index 7f34d1fc30..a2447d43eb 100644 --- a/apps/app_queue.c +++ b/apps/app_queue.c @@ -3047,17 +3047,6 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce if (need_weight) AST_LIST_UNLOCK(&queues); lpeer = wait_for_answer(qe, outgoing, &to, &digit, numbusies, ast_test_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT), forwardsallowed); - /* 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_channel_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(qe, outgoing); diff --git a/res/res_features.c b/res/res_features.c index 63aafa5712..66106e851d 100644 --- a/res/res_features.c +++ b/res/res_features.c @@ -2092,6 +2092,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_channel_datastore_free(di_datastore); + } + } + ast_channel_unlock(chan); +} + int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast_bridge_config *config) { /* Copy voice back and forth between the two channels. Give the peer @@ -2249,6 +2265,12 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast ast_clear_flag(bridge_cdr, AST_CDR_FLAG_DIALED); } + /* 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 */