diff options
Diffstat (limited to 'main')
-rw-r--r-- | main/channel.c | 6 | ||||
-rw-r--r-- | main/core_unreal.c | 55 | ||||
-rw-r--r-- | main/message.c | 4 | ||||
-rw-r--r-- | main/pbx.c | 2 |
4 files changed, 45 insertions, 22 deletions
diff --git a/main/channel.c b/main/channel.c index d669baf85..418e6a772 100644 --- a/main/channel.c +++ b/main/channel.c @@ -1017,6 +1017,12 @@ __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char ast_channel_internal_finalize(tmp); ast_atomic_fetchadd_int(&chancount, +1); + + /* You might scream "locking inversion" at seeing this but it is actually perfectly fine. + * Since the channel was just created nothing can know about it yet or even acquire it. + */ + ast_channel_lock(tmp); + ao2_link(channels, tmp); /* diff --git a/main/core_unreal.c b/main/core_unreal.c index 7e457f484..7ab7da765 100644 --- a/main/core_unreal.c +++ b/main/core_unreal.c @@ -906,57 +906,72 @@ struct ast_channel *ast_unreal_new_channels(struct ast_unreal_pvt *p, */ if (!(owner = ast_channel_alloc(1, semi1_state, NULL, NULL, NULL, exten, context, linkedid, 0, - "%s/%s-%08x;1", tech->type, p->name, generated_seqno)) - || !(chan = ast_channel_alloc(1, semi2_state, NULL, NULL, NULL, - exten, context, ast_channel_linkedid(owner), 0, - "%s/%s-%08x;2", tech->type, p->name, generated_seqno))) { - if (owner) { - owner = ast_channel_release(owner); - } - ast_log(LOG_WARNING, "Unable to allocate channel structure(s)\n"); + "%s/%s-%08x;1", tech->type, p->name, generated_seqno))) { + ast_log(LOG_WARNING, "Unable to allocate owner channel structure\n"); return NULL; } if (callid) { ast_channel_callid_set(owner, callid); - ast_channel_callid_set(chan, callid); } ast_channel_tech_set(owner, tech); - ast_channel_tech_set(chan, tech); + ao2_ref(p, +1); ast_channel_tech_pvt_set(owner, p); - ast_channel_tech_pvt_set(chan, p); ast_format_cap_copy(ast_channel_nativeformats(owner), p->reqcap); - ast_format_cap_copy(ast_channel_nativeformats(chan), p->reqcap); /* Determine our read/write format and set it on each channel */ ast_best_codec(p->reqcap, &fmt); ast_format_copy(ast_channel_writeformat(owner), &fmt); - ast_format_copy(ast_channel_writeformat(chan), &fmt); ast_format_copy(ast_channel_rawwriteformat(owner), &fmt); - ast_format_copy(ast_channel_rawwriteformat(chan), &fmt); ast_format_copy(ast_channel_readformat(owner), &fmt); - ast_format_copy(ast_channel_readformat(chan), &fmt); ast_format_copy(ast_channel_rawreadformat(owner), &fmt); - ast_format_copy(ast_channel_rawreadformat(chan), &fmt); ast_set_flag(ast_channel_flags(owner), AST_FLAG_DISABLE_DEVSTATE_CACHE); - ast_set_flag(ast_channel_flags(chan), AST_FLAG_DISABLE_DEVSTATE_CACHE); ast_jb_configure(owner, &p->jb_conf); if (ast_channel_cc_params_init(owner, requestor ? ast_channel_get_cc_config_params((struct ast_channel *) requestor) : NULL)) { + ao2_ref(p, -1); + ast_channel_unlock(owner); ast_channel_release(owner); - ast_channel_release(chan); return NULL; } - /* Give the private a ref for each channel. */ - ao2_ref(p, +2); p->owner = owner; + ast_channel_unlock(owner); + + if (!(chan = ast_channel_alloc(1, semi2_state, NULL, NULL, NULL, + exten, context, ast_channel_linkedid(owner), 0, + "%s/%s-%08x;2", tech->type, p->name, generated_seqno))) { + ast_log(LOG_WARNING, "Unable to allocate chan channel structure\n"); + ao2_ref(p, -1); + ast_channel_release(owner); + return NULL; + } + + if (callid) { + ast_channel_callid_set(chan, callid); + } + + ast_channel_tech_set(chan, tech); + ao2_ref(p, +1); + ast_channel_tech_pvt_set(chan, p); + + ast_format_cap_copy(ast_channel_nativeformats(chan), p->reqcap); + + /* Format was already determined when setting up owner */ + ast_format_copy(ast_channel_writeformat(chan), &fmt); + ast_format_copy(ast_channel_rawwriteformat(chan), &fmt); + ast_format_copy(ast_channel_readformat(chan), &fmt); + ast_format_copy(ast_channel_rawreadformat(chan), &fmt); + + ast_set_flag(ast_channel_flags(chan), AST_FLAG_DISABLE_DEVSTATE_CACHE); + p->chan = chan; + ast_channel_unlock(chan); return owner; } diff --git a/main/message.c b/main/message.c index ef2c97f1f..7690e4a88 100644 --- a/main/message.c +++ b/main/message.c @@ -678,9 +678,9 @@ static struct ast_channel *create_msg_q_chan(void) return NULL; } - ast_channel_unlink(chan); - ast_channel_tech_set(chan, &msg_chan_tech_hack); + ast_channel_unlock(chan); + ast_channel_unlink(chan); if (!(ds = ast_datastore_alloc(&msg_datastore, NULL))) { ast_hangup(chan); diff --git a/main/pbx.c b/main/pbx.c index 6b9bd5ebf..726677f4a 100644 --- a/main/pbx.c +++ b/main/pbx.c @@ -10365,6 +10365,8 @@ static int pbx_outgoing_attempt(const char *type, struct ast_format_cap *cap, co snprintf(failed_reason, sizeof(failed_reason), "%d", ast_dial_reason(outgoing->dial, 0)); pbx_builtin_setvar_helper(failed, "REASON", failed_reason); + ast_channel_unlock(failed); + if (ast_pbx_run(failed)) { ast_log(LOG_ERROR, "Unable to run PBX on '%s'\n", ast_channel_name(failed)); ast_hangup(failed); |