If the datastore has been moved to another channel due to a masquerade, then

freeing the datastore here causes an eventual double free when the new channel
hangs up. We should only free the datastore if we were able to successfully remove
it from the channel we are referencing (i.e. the datastore was not moved).

(closes issue #12359)
Reported by: pguido



git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@114112 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Mark Michelson
2008-04-14 16:24:22 +00:00
parent f689fffa71
commit f1683753b8
2 changed files with 15 additions and 4 deletions

View File

@@ -1320,8 +1320,14 @@ 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);
ast_channel_datastore_remove(chan, datastore);
ast_channel_datastore_free(datastore);
/* 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;

View File

@@ -2753,8 +2753,13 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce
if (use_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);
if (datastore) {
ast_channel_datastore_remove(qe->chan, datastore);
/* 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 (datastore && !ast_channel_datastore_remove(qe->chan, datastore)) {
ast_channel_datastore_free(datastore);
}
ast_mutex_lock(&qe->parent->lock);