From e2630fcd516b8f794bf342d9fd267b0c905e79ce Mon Sep 17 00:00:00 2001 From: Joshua Colp <jcolp@digium.com> Date: Wed, 18 Dec 2013 19:28:05 +0000 Subject: [PATCH] channels: Return allocated channels locked. This change makes ast_channel_alloc return allocated channels locked. By doing so no other thread can acquire, lock, and manipulate the channel before it is completely set up. (closes issue AST-1256) Review: https://reviewboard.asterisk.org/r/3067/ ........ Merged revisions 404204 from http://svn.asterisk.org/svn/asterisk/branches/12 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@404210 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- addons/chan_mobile.c | 2 + addons/chan_ooh323.c | 1 - apps/app_meetme.c | 2 + apps/app_voicemail.c | 2 + apps/confbridge/conf_chan_record.c | 2 + channels/chan_alsa.c | 2 + channels/chan_console.c | 2 + channels/chan_dahdi.c | 2 + channels/chan_gtalk.c | 2 + channels/chan_h323.c | 1 + channels/chan_iax2.c | 3 ++ channels/chan_jingle.c | 2 + channels/chan_mgcp.c | 2 + channels/chan_misdn.c | 4 ++ channels/chan_motif.c | 2 + channels/chan_multicast_rtp.c | 2 + channels/chan_nbs.c | 1 + channels/chan_oss.c | 1 + channels/chan_phone.c | 1 + channels/chan_pjsip.c | 29 +++++++------- channels/chan_sip.c | 2 +- channels/chan_skinny.c | 4 ++ channels/chan_unistim.c | 2 + channels/chan_vpb.cc | 2 + include/asterisk/channel.h | 5 ++- main/channel.c | 6 +++ main/core_unreal.c | 55 ++++++++++++++++---------- main/message.c | 4 +- main/pbx.c | 2 + res/parking/parking_tests.c | 2 + res/res_calendar.c | 2 + res/res_stasis_snoop.c | 62 ++++++++++++++++-------------- tests/test_app.c | 12 ++++-- tests/test_cdr.c | 18 +++++++++ tests/test_cel.c | 5 +++ tests/test_stasis_channels.c | 6 +++ tests/test_substitution.c | 1 + tests/test_voicemail_api.c | 2 + 38 files changed, 187 insertions(+), 70 deletions(-) diff --git a/addons/chan_mobile.c b/addons/chan_mobile.c index 2cf7c7dbdd..a76d778c4c 100644 --- a/addons/chan_mobile.c +++ b/addons/chan_mobile.c @@ -879,6 +879,8 @@ static struct ast_channel *mbl_new(int state, struct mbl_pvt *pvt, char *cid_num ast_channel_set_fd(chn, 0, pvt->sco_socket); } + ast_channel_unlock(chn); + return chn; e_return: diff --git a/addons/chan_ooh323.c b/addons/chan_ooh323.c index ff0a030adf..d89e00c2e9 100644 --- a/addons/chan_ooh323.c +++ b/addons/chan_ooh323.c @@ -395,7 +395,6 @@ static struct ast_channel *ooh323_new(struct ooh323_pvt *i, int state, ast_mutex_lock(&i->lock); if (ch) { - ast_channel_lock(ch); ast_channel_tech_set(ch, &ooh323_tech); if (cap) diff --git a/apps/app_meetme.c b/apps/app_meetme.c index ffd55e70df..feea3b6c59 100644 --- a/apps/app_meetme.c +++ b/apps/app_meetme.c @@ -8140,6 +8140,8 @@ AST_TEST_DEFINE(test_meetme_data_provider) return AST_TEST_FAIL; } + ast_channel_unlock(chan); + cnf = build_conf("9898", "", "1234", 1, 1, 1, chan, test); if (!cnf) { ast_test_status_update(test, "Build of test conference 9898 failed\n"); diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c index dbcd283559..4dffbbef07 100644 --- a/apps/app_voicemail.c +++ b/apps/app_voicemail.c @@ -13744,6 +13744,8 @@ AST_TEST_DEFINE(test_voicemail_vmsayname) ast_format_set(ast_channel_rawreadformat(test_channel1), AST_FORMAT_GSM, 0); ast_channel_tech_set(test_channel1, &fake_tech); + ast_channel_unlock(test_channel1); + ast_test_status_update(test, "Test playing of extension when greeting is not available...\n"); snprintf(dir, sizeof(dir), "%s@%s", TEST_EXTENSION, TEST_CONTEXT); /* not a dir, don't get confused */ if (!(res = vmsayname_exec(test_channel1, dir))) { diff --git a/apps/confbridge/conf_chan_record.c b/apps/confbridge/conf_chan_record.c index 7080d118c9..78d1f272c3 100644 --- a/apps/confbridge/conf_chan_record.c +++ b/apps/confbridge/conf_chan_record.c @@ -66,6 +66,7 @@ static struct ast_channel *rec_request(const char *type, struct ast_format_cap * return NULL; } if (ast_channel_add_bridge_role(chan, "recorder")) { + ast_channel_unlock(chan); ast_channel_release(chan); return NULL; } @@ -76,6 +77,7 @@ static struct ast_channel *rec_request(const char *type, struct ast_format_cap * ast_format_copy(ast_channel_rawwriteformat(chan), &format); ast_format_copy(ast_channel_readformat(chan), &format); ast_format_copy(ast_channel_rawreadformat(chan), &format); + ast_channel_unlock(chan); return chan; } diff --git a/channels/chan_alsa.c b/channels/chan_alsa.c index 60bbacbb86..1d2d5f9f28 100644 --- a/channels/chan_alsa.c +++ b/channels/chan_alsa.c @@ -602,6 +602,8 @@ static struct ast_channel *alsa_new(struct chan_alsa_pvt *p, int state, const ch ast_channel_stage_snapshot_done(tmp); + ast_channel_unlock(tmp); + if (state != AST_STATE_DOWN) { if (ast_pbx_start(tmp)) { ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp)); diff --git a/channels/chan_console.c b/channels/chan_console.c index 922c53b426..e37b565c50 100644 --- a/channels/chan_console.c +++ b/channels/chan_console.c @@ -445,6 +445,8 @@ static struct ast_channel *console_new(struct console_pvt *pvt, const char *ext, ast_channel_stage_snapshot_done(chan); + ast_channel_unlock(chan); + if (state != AST_STATE_DOWN) { if (ast_pbx_start(chan)) { ast_channel_hangupcause_set(chan, AST_CAUSE_SWITCH_CONGESTION); diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c index 2eba958a8b..636d8863f0 100644 --- a/channels/chan_dahdi.c +++ b/channels/chan_dahdi.c @@ -9097,6 +9097,8 @@ static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpb ast_channel_stage_snapshot_done(tmp); + ast_channel_unlock(tmp); + ast_module_ref(ast_module_info->self); dahdi_ami_channel_event(i, tmp); diff --git a/channels/chan_gtalk.c b/channels/chan_gtalk.c index d6a0949419..bec4401034 100644 --- a/channels/chan_gtalk.c +++ b/channels/chan_gtalk.c @@ -1227,6 +1227,8 @@ static struct ast_channel *gtalk_new(struct gtalk *client, struct gtalk_pvt *i, ast_channel_stage_snapshot_done(tmp); + ast_channel_unlock(tmp); + if (state != AST_STATE_DOWN && ast_pbx_start(tmp)) { ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp)); ast_channel_hangupcause_set(tmp, AST_CAUSE_SWITCH_CONGESTION); diff --git a/channels/chan_h323.c b/channels/chan_h323.c index 22dba3c183..1c9bb2ad07 100644 --- a/channels/chan_h323.c +++ b/channels/chan_h323.c @@ -1139,6 +1139,7 @@ static struct ast_channel *__oh323_new(struct oh323_pvt *pvt, int state, const c } if (pvt->cd.transfer_capability >= 0) ast_channel_transfercapability_set(ch, pvt->cd.transfer_capability); + ast_channel_unlock(ch); if (state != AST_STATE_DOWN) { if (ast_pbx_start(ch)) { ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(ch)); diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c index 84a72c850c..b89ae824be 100644 --- a/channels/chan_iax2.c +++ b/channels/chan_iax2.c @@ -5694,6 +5694,7 @@ static struct ast_channel *ast_iax2_new(int callno, int state, iax2_format capab if (tmp) { /* unlock and relock iaxsl[callno] to preserve locking order */ ast_mutex_unlock(&iaxsl[callno]); + ast_channel_unlock(tmp); tmp = ast_channel_release(tmp); ast_mutex_lock(&iaxsl[callno]); } @@ -5804,6 +5805,8 @@ static struct ast_channel *ast_iax2_new(int callno, int state, iax2_format capab ast_channel_stage_snapshot_done(tmp); + ast_channel_unlock(tmp); + if (state != AST_STATE_DOWN) { if (ast_pbx_start(tmp)) { ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp)); diff --git a/channels/chan_jingle.c b/channels/chan_jingle.c index 56c15b193f..c1c5026871 100644 --- a/channels/chan_jingle.c +++ b/channels/chan_jingle.c @@ -942,6 +942,8 @@ static struct ast_channel *jingle_new(struct jingle *client, struct jingle_pvt * ast_channel_stage_snapshot_done(tmp); + ast_channel_unlock(tmp); + if (state != AST_STATE_DOWN && ast_pbx_start(tmp)) { ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp)); ast_channel_hangupcause_set(tmp, AST_CAUSE_SWITCH_CONGESTION); diff --git a/channels/chan_mgcp.c b/channels/chan_mgcp.c index 84fb3b2256..a6f75e6c32 100644 --- a/channels/chan_mgcp.c +++ b/channels/chan_mgcp.c @@ -1571,6 +1571,8 @@ static struct ast_channel *mgcp_new(struct mgcp_subchannel *sub, int state, cons ast_channel_stage_snapshot_done(tmp); + ast_channel_unlock(tmp); + if (state != AST_STATE_DOWN) { if (ast_pbx_start(tmp)) { ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp)); diff --git a/channels/chan_misdn.c b/channels/chan_misdn.c index 38197c6381..6dd9adf6ac 100644 --- a/channels/chan_misdn.c +++ b/channels/chan_misdn.c @@ -8226,6 +8226,8 @@ static struct ast_channel *misdn_new(struct chan_list *chlist, int state, char ast_channel_rings_set(tmp, (state == AST_STATE_RING) ? 1 : 0); ast_jb_configure(tmp, misdn_get_global_jbconf()); + + ast_channel_unlock(tmp); } else { chan_misdn_log(-1, 0, "Unable to allocate channel structure\n"); } @@ -8949,6 +8951,8 @@ static void misdn_cc_pbx_notify(long record_id, const struct misdn_cc_notify *no ast_free(ast_channel_dialed(chan)->number.str); ast_channel_dialed(chan)->number.str = ast_strdup(notify->exten); + ast_channel_unlock(chan); + if (ast_pbx_start(chan)) { ast_log(LOG_WARNING, "Unable to start pbx channel %s!\n", ast_channel_name(chan)); ast_channel_release(chan); diff --git a/channels/chan_motif.c b/channels/chan_motif.c index 1e7ee3cce6..2c2b270077 100644 --- a/channels/chan_motif.c +++ b/channels/chan_motif.c @@ -853,6 +853,8 @@ static struct ast_channel *jingle_new(struct jingle_endpoint *endpoint, struct j ast_channel_stage_snapshot_done(chan); + ast_channel_unlock(chan); + return chan; } diff --git a/channels/chan_multicast_rtp.c b/channels/chan_multicast_rtp.c index 1b9e4d31f2..e3d8f9b130 100644 --- a/channels/chan_multicast_rtp.c +++ b/channels/chan_multicast_rtp.c @@ -166,6 +166,8 @@ static struct ast_channel *multicast_rtp_request(const char *type, struct ast_fo ast_channel_tech_pvt_set(chan, instance); + ast_channel_unlock(chan); + return chan; failure: diff --git a/channels/chan_nbs.c b/channels/chan_nbs.c index 1d8c59d4e1..7cce241135 100644 --- a/channels/chan_nbs.c +++ b/channels/chan_nbs.c @@ -239,6 +239,7 @@ static struct ast_channel *nbs_new(struct nbs_pvt *i, int state, const char *lin ast_channel_language_set(tmp, ""); i->owner = tmp; i->u = ast_module_user_add(tmp); + ast_channel_unlock(tmp); if (state != AST_STATE_DOWN) { if (ast_pbx_start(tmp)) { ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp)); diff --git a/channels/chan_oss.c b/channels/chan_oss.c index 5ae18f362e..3a52ac9db4 100644 --- a/channels/chan_oss.c +++ b/channels/chan_oss.c @@ -829,6 +829,7 @@ static struct ast_channel *oss_new(struct chan_oss_pvt *o, char *ext, char *ctx, o->owner = c; ast_module_ref(ast_module_info->self); ast_jb_configure(c, &global_jbconf); + ast_channel_unlock(c); if (state != AST_STATE_DOWN) { if (ast_pbx_start(c)) { ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(c)); diff --git a/channels/chan_phone.c b/channels/chan_phone.c index c1a24b8b1b..ba14a435e2 100644 --- a/channels/chan_phone.c +++ b/channels/chan_phone.c @@ -901,6 +901,7 @@ static struct ast_channel *phone_new(struct phone_pvt *i, int state, char *cntx, i->owner = tmp; ast_module_ref(ast_module_info->self); + ast_channel_unlock(tmp); if (state != AST_STATE_DOWN) { if (state == AST_STATE_RING) { ioctl(ast_channel_fd(tmp, 0), PHONE_RINGBACK); diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c index 21a79f0edb..cd209d243a 100644 --- a/channels/chan_pjsip.c +++ b/channels/chan_pjsip.c @@ -359,24 +359,14 @@ static struct ast_channel *chan_pjsip_new(struct ast_sip_session *session, int s ast_channel_tech_set(chan, &chan_pjsip_tech); if (!(channel = ast_sip_channel_pvt_alloc(pvt, session))) { + ast_channel_unlock(chan); ast_hangup(chan); return NULL; } ast_channel_stage_snapshot(chan); - /* If res_pjsip_session is ever updated to create/destroy ast_sip_session_media - * during a call such as if multiple same-type stream support is introduced, - * these will need to be recaptured as well */ - pvt->media[SIP_MEDIA_AUDIO] = ao2_find(session->media, "audio", OBJ_KEY); - pvt->media[SIP_MEDIA_VIDEO] = ao2_find(session->media, "video", OBJ_KEY); ast_channel_tech_pvt_set(chan, channel); - if (pvt->media[SIP_MEDIA_AUDIO] && pvt->media[SIP_MEDIA_AUDIO]->rtp) { - ast_rtp_instance_set_channel_id(pvt->media[SIP_MEDIA_AUDIO]->rtp, ast_channel_uniqueid(chan)); - } - if (pvt->media[SIP_MEDIA_VIDEO] && pvt->media[SIP_MEDIA_VIDEO]->rtp) { - ast_rtp_instance_set_channel_id(pvt->media[SIP_MEDIA_VIDEO]->rtp, ast_channel_uniqueid(chan)); - } if (ast_format_cap_is_empty(session->req_caps) || !ast_format_cap_has_joint(session->req_caps, session->endpoint->media.codecs)) { ast_format_cap_copy(ast_channel_nativeformats(chan), session->endpoint->media.codecs); @@ -418,9 +408,22 @@ static struct ast_channel *chan_pjsip_new(struct ast_sip_session *session, int s ast_channel_zone_set(chan, zone); } - ast_endpoint_add_channel(session->endpoint->persistent, chan); - ast_channel_stage_snapshot_done(chan); + ast_channel_unlock(chan); + + /* If res_pjsip_session is ever updated to create/destroy ast_sip_session_media + * during a call such as if multiple same-type stream support is introduced, + * these will need to be recaptured as well */ + pvt->media[SIP_MEDIA_AUDIO] = ao2_find(session->media, "audio", OBJ_KEY); + pvt->media[SIP_MEDIA_VIDEO] = ao2_find(session->media, "video", OBJ_KEY); + if (pvt->media[SIP_MEDIA_AUDIO] && pvt->media[SIP_MEDIA_AUDIO]->rtp) { + ast_rtp_instance_set_channel_id(pvt->media[SIP_MEDIA_AUDIO]->rtp, ast_channel_uniqueid(chan)); + } + if (pvt->media[SIP_MEDIA_VIDEO] && pvt->media[SIP_MEDIA_VIDEO]->rtp) { + ast_rtp_instance_set_channel_id(pvt->media[SIP_MEDIA_VIDEO]->rtp, ast_channel_uniqueid(chan)); + } + + ast_endpoint_add_channel(session->endpoint->persistent, chan); return chan; } diff --git a/channels/chan_sip.c b/channels/chan_sip.c index a7649127e7..0fde84e2df 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -8100,6 +8100,7 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit if (i->relatedpeer && i->relatedpeer->endpoint) { if (ast_endpoint_add_channel(i->relatedpeer->endpoint, tmp)) { + ast_channel_unlock(tmp); ast_channel_unref(tmp); sip_pvt_lock(i); return NULL; @@ -8113,7 +8114,6 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit ast_channel_callid_set(tmp, callid); } - ast_channel_lock(tmp); sip_pvt_lock(i); ast_channel_cc_params_init(tmp, i->cc_params); ast_channel_caller(tmp)->id.tag = ast_strdup(i->cid_tag); diff --git a/channels/chan_skinny.c b/channels/chan_skinny.c index a65862ff3c..bb270d6a9d 100644 --- a/channels/chan_skinny.c +++ b/channels/chan_skinny.c @@ -5393,6 +5393,8 @@ static struct ast_channel *skinny_new(struct skinny_line *l, struct skinny_subli sub = ast_calloc(1, sizeof(*sub)); if (!sub) { ast_log(LOG_WARNING, "Unable to allocate Skinny subchannel\n"); + ast_channel_unlock(tmp); + ast_channel_unref(tmp); return NULL; } else { ast_mutex_init(&sub->lock); @@ -5500,6 +5502,8 @@ static struct ast_channel *skinny_new(struct skinny_line *l, struct skinny_subli ast_channel_stage_snapshot_done(tmp); + ast_channel_unlock(tmp); + if (state != AST_STATE_DOWN) { if (ast_pbx_start(tmp)) { ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp)); diff --git a/channels/chan_unistim.c b/channels/chan_unistim.c index 547cd7c2f6..21bbbc1e82 100644 --- a/channels/chan_unistim.c +++ b/channels/chan_unistim.c @@ -5628,6 +5628,8 @@ static struct ast_channel *unistim_new(struct unistim_subchannel *sub, int state ast_channel_stage_snapshot_done(tmp); + ast_channel_unlock(tmp); + if (state != AST_STATE_DOWN) { if (unistimdebug) { ast_verb(0, "Starting pbx in unistim_new\n"); diff --git a/channels/chan_vpb.cc b/channels/chan_vpb.cc index 12f27249b1..39d78cc332 100644 --- a/channels/chan_vpb.cc +++ b/channels/chan_vpb.cc @@ -2472,6 +2472,8 @@ static struct ast_channel *vpb_new(struct vpb_pvt *me, enum ast_channel_state st if (!ast_strlen_zero(me->language)) ast_channel_language_set(tmp, me->language); + ast_channel_unlock(tmp); + me->owner = tmp; me->bridge = NULL; diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h index 03d9aef68a..51530a82bf 100644 --- a/include/asterisk/channel.h +++ b/include/asterisk/channel.h @@ -791,7 +791,8 @@ typedef int(*ast_timing_func_t)(const void *data); * active channels in the system. The hash key is based on the channel name. Because * of this, if you want to change the name, you _must_ use ast_change_name(), not change * the name field directly. When ast_channel_alloc() returns a channel pointer, you now - * hold a reference to that channel. In most cases this reference is given to ast_pbx_run(). + * hold both a reference to that channel and a lock on the channel. Once the channel has + * been set up the lock can be released. In most cases the reference is given to ast_pbx_run(). * * \par Channel Locking * There is a lock associated with every ast_channel. It is allocated internally via astobj2. @@ -1122,6 +1123,7 @@ struct ast_datastore *ast_channel_datastore_find(struct ast_channel *chan, const * \note Absolutely _NO_ channel locks should be held before calling this function. * \note By default, new channels are set to the "s" extension * and "default" context. + * \note Since 12.0.0 this function returns with the newly created channel locked. */ struct ast_channel * attribute_malloc __attribute__((format(printf, 13, 14))) __ast_channel_alloc(int needqueue, int state, const char *cid_num, @@ -1140,6 +1142,7 @@ struct ast_channel * attribute_malloc __attribute__((format(printf, 13, 14))) * \note Absolutely _NO_ channel locks should be held before calling this function. * \note By default, new channels are set to the "s" extension * and "default" context. + * \note Since 12.0.0 this function returns with the newly created channel locked. */ #define ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, linkedid, amaflag, ...) \ __ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, linkedid, amaflag, \ diff --git a/main/channel.c b/main/channel.c index d669baf85e..418e6a7727 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 7e457f4849..7ab7da7650 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 ef2c97f1fa..7690e4a886 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 6b9bd5ebfd..726677f4aa 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); diff --git a/res/parking/parking_tests.c b/res/parking/parking_tests.c index e046ca8cf8..f6767769ae 100644 --- a/res/parking/parking_tests.c +++ b/res/parking/parking_tests.c @@ -63,6 +63,8 @@ static struct ast_channel *create_alice_channel(void) ast_channel_set_caller(alice, &alice_callerid, NULL); + ast_channel_unlock(alice); + return alice; } diff --git a/res/res_calendar.c b/res/res_calendar.c index eebd7b480e..c36e5cf0a7 100644 --- a/res/res_calendar.c +++ b/res/res_calendar.c @@ -766,6 +766,8 @@ static void *do_notify(void *data) /* clear native formats and set to slinear. write format is signlear so just use that to set it */ ast_format_cap_set(ast_channel_nativeformats(chan), ast_channel_writeformat(chan)); + ast_channel_unlock(chan); + if (!(datastore = ast_datastore_alloc(&event_notification_datastore, NULL))) { ast_log(LOG_ERROR, "Could not allocate datastore, notification not being sent!\n"); goto notify_cleanup; diff --git a/res/res_stasis_snoop.c b/res/res_stasis_snoop.c index 1a40112d1f..65186d14e6 100644 --- a/res/res_stasis_snoop.c +++ b/res/res_stasis_snoop.c @@ -274,12 +274,21 @@ static int snoop_setup_audiohook(struct ast_channel *chan, enum ast_audiohook_ty return ast_audiohook_attach(chan, audiohook); } +/*! \brief Helper function which gets the format for a Snoop channel based on the channel being snooped on */ +static void snoop_determine_format(struct ast_channel *chan, struct stasis_app_snoop *snoop) +{ + SCOPED_CHANNELLOCK(lock, chan); + unsigned int rate = MAX(ast_format_rate(ast_channel_rawwriteformat(chan)), + ast_format_rate(ast_channel_rawreadformat(chan))); + + ast_format_set(&snoop->spy_format, ast_format_slin_by_rate(rate), 0); +} + struct ast_channel *stasis_app_control_snoop(struct ast_channel *chan, enum stasis_app_snoop_direction spy, enum stasis_app_snoop_direction whisper, const char *app, const char *app_args) { RAII_VAR(struct stasis_app_snoop *, snoop, NULL, ao2_cleanup); - unsigned int rate; pthread_t thread; if (spy == STASIS_SNOOP_DIRECTION_NONE && @@ -310,6 +319,9 @@ struct ast_channel *stasis_app_control_snoop(struct ast_channel *chan, } ast_timer_set_rate(snoop->timer, 1000 / SNOOP_INTERVAL); + /* Determine which signed linear format should be used */ + snoop_determine_format(chan, snoop); + /* Allocate a Snoop channel and set up various parameters */ snoop->chan = ast_channel_alloc(1, AST_STATE_UP, "", "", "", "", "", "", 0, "Snoop/%s-%08x", ast_channel_uniqueid(chan), ast_atomic_fetchadd_int((int *)&chan_idx, +1)); @@ -327,39 +339,33 @@ struct ast_channel *stasis_app_control_snoop(struct ast_channel *chan, ast_channel_tech_pvt_set(snoop->chan, snoop); ast_channel_set_fd(snoop->chan, 0, ast_timer_fd(snoop->timer)); - { - SCOPED_CHANNELLOCK(lock, chan); + /* The format on the Snoop channel will be this signed linear format, and it will never change */ + ast_format_cap_set(ast_channel_nativeformats(snoop->chan), &snoop->spy_format); + ast_format_copy(ast_channel_writeformat(snoop->chan), &snoop->spy_format); + ast_format_copy(ast_channel_rawwriteformat(snoop->chan), &snoop->spy_format); + ast_format_copy(ast_channel_readformat(snoop->chan), &snoop->spy_format); + ast_format_copy(ast_channel_rawreadformat(snoop->chan), &snoop->spy_format); - /* Determine the "best" signed linear format capable by the channel we are snooping on */ - rate = MAX(ast_format_rate(ast_channel_rawwriteformat(chan)), ast_format_rate(ast_channel_rawreadformat(chan))); - ast_format_set(&snoop->spy_format, ast_format_slin_by_rate(rate), 0); + ast_channel_unlock(snoop->chan); - /* The format on the Snoop channel will be this signed linear format, and it will never change */ - ast_format_cap_set(ast_channel_nativeformats(snoop->chan), &snoop->spy_format); - ast_format_copy(ast_channel_writeformat(snoop->chan), &snoop->spy_format); - ast_format_copy(ast_channel_rawwriteformat(snoop->chan), &snoop->spy_format); - ast_format_copy(ast_channel_readformat(snoop->chan), &snoop->spy_format); - ast_format_copy(ast_channel_rawreadformat(snoop->chan), &snoop->spy_format); - - if (spy != STASIS_SNOOP_DIRECTION_NONE) { - if (snoop_setup_audiohook(chan, AST_AUDIOHOOK_TYPE_SPY, spy, &snoop->spy_direction, &snoop->spy)) { - ast_hangup(snoop->chan); - return NULL; - } - - snoop->spy_samples = rate / (1000 / SNOOP_INTERVAL); - snoop->spy_active = 1; + if (spy != STASIS_SNOOP_DIRECTION_NONE) { + if (snoop_setup_audiohook(chan, AST_AUDIOHOOK_TYPE_SPY, spy, &snoop->spy_direction, &snoop->spy)) { + ast_hangup(snoop->chan); + return NULL; } - /* If whispering is enabled set up the audiohook */ - if (whisper != STASIS_SNOOP_DIRECTION_NONE) { - if (snoop_setup_audiohook(chan, AST_AUDIOHOOK_TYPE_WHISPER, whisper, &snoop->whisper_direction, &snoop->whisper)) { - ast_hangup(snoop->chan); - return NULL; - } + snoop->spy_samples = ast_format_rate(&snoop->spy_format) / (1000 / SNOOP_INTERVAL); + snoop->spy_active = 1; + } - snoop->whisper_active = 1; + /* If whispering is enabled set up the audiohook */ + if (whisper != STASIS_SNOOP_DIRECTION_NONE) { + if (snoop_setup_audiohook(chan, AST_AUDIOHOOK_TYPE_WHISPER, whisper, &snoop->whisper_direction, &snoop->whisper)) { + ast_hangup(snoop->chan); + return NULL; } + + snoop->whisper_active = 1; } /* Create the thread which services the Snoop channel */ diff --git a/tests/test_app.c b/tests/test_app.c index f47b052e52..92da42022d 100644 --- a/tests/test_app.c +++ b/tests/test_app.c @@ -175,21 +175,25 @@ AST_TEST_DEFINE(app_group) "'%s', '%s', '%s', '%s'\n", group1_full, group2_full, category1_full, category2_full); if (!(test_channel1 = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, - NULL, NULL, 0, 0, "TestChannel1"))) { + NULL, NULL, 0, 0, "TestChannel1"))) { goto exit_group_test; } + ast_channel_unlock(test_channel1); if (!(test_channel2 = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, - NULL, NULL, 0, 0, "TestChannel2"))) { + NULL, NULL, 0, 0, "TestChannel2"))) { goto exit_group_test; } + ast_channel_unlock(test_channel2); if (!(test_channel3 = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, - NULL, NULL, 0, 0, "TestChannel3"))) { + NULL, NULL, 0, 0, "TestChannel3"))) { goto exit_group_test; } + ast_channel_unlock(test_channel3); if (!(test_channel4 = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, - NULL, NULL, 0, 0, "TestChannel4"))) { + NULL, NULL, 0, 0, "TestChannel4"))) { goto exit_group_test; } + ast_channel_unlock(test_channel4); ast_app_group_set_channel(test_channel1, group1_full); ast_app_group_set_channel(test_channel2, group2_full); diff --git a/tests/test_cdr.c b/tests/test_cdr.c index 6d1626b368..e70a0641b0 100644 --- a/tests/test_cdr.c +++ b/tests/test_cdr.c @@ -238,6 +238,7 @@ static void clear_mock_cdr_backend(void) ast_channel_set_caller((channel_var), (caller_id), NULL); \ ast_copy_string((expected_record)->uniqueid, ast_channel_uniqueid((channel_var)), sizeof((expected_record)->uniqueid)); \ ast_copy_string((expected_record)->linkedid, ast_channel_linkedid((channel_var)), sizeof((expected_record)->linkedid)); \ + ast_channel_unlock((channel_var)); \ } while (0) /*! \brief Create a \ref test_cdr_chan_tech for Bob, and set the expected @@ -247,6 +248,7 @@ static void clear_mock_cdr_backend(void) ast_channel_set_caller((channel_var), (caller_id), NULL); \ ast_copy_string((expected_record)->uniqueid, ast_channel_uniqueid((channel_var)), sizeof((expected_record)->uniqueid)); \ ast_copy_string((expected_record)->linkedid, ast_channel_linkedid((channel_var)), sizeof((expected_record)->linkedid)); \ + ast_channel_unlock((channel_var)); \ } while (0) /*! \brief Create a \ref test_cdr_chan_tech for Charlie, and set the expected @@ -256,6 +258,7 @@ static void clear_mock_cdr_backend(void) ast_channel_set_caller((channel_var), (caller_id), NULL); \ ast_copy_string((expected_record)->uniqueid, ast_channel_uniqueid((channel_var)), sizeof((expected_record)->uniqueid)); \ ast_copy_string((expected_record)->linkedid, ast_channel_linkedid((channel_var)), sizeof((expected_record)->linkedid)); \ + ast_channel_unlock((channel_var)); \ } while (0) /*! \brief Create a \ref test_cdr_chan_tech for Charlie, and set the expected @@ -265,6 +268,7 @@ static void clear_mock_cdr_backend(void) ast_channel_set_caller((channel_var), (caller_id), NULL); \ ast_copy_string((expected_record)->uniqueid, ast_channel_uniqueid((channel_var)), sizeof((expected_record)->uniqueid)); \ ast_copy_string((expected_record)->linkedid, ast_channel_linkedid((channel_var)), sizeof((expected_record)->linkedid)); \ + ast_channel_unlock((channel_var)); \ } while (0) /*! \brief Emulate a channel entering into an application */ @@ -563,6 +567,7 @@ AST_TEST_DEFINE(test_cdr_outbound_bridged_call) ast_test_validate(test, !ast_bridge_impart(bridge, chan_alice, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE)); chan_bob = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "200", NULL, NULL, ast_channel_linkedid(chan_alice), 0, CHANNEL_TECH_NAME "/Bob"); + ast_channel_unlock(chan_bob); ast_copy_string(bob_expected.linkedid, ast_channel_linkedid(chan_bob), sizeof(bob_expected.linkedid)); ast_copy_string(bob_expected.uniqueid, ast_channel_uniqueid(chan_bob), sizeof(bob_expected.uniqueid)); ast_set_flag(ast_channel_flags(chan_bob), AST_FLAG_OUTGOING); @@ -1133,6 +1138,7 @@ AST_TEST_DEFINE(test_cdr_dial_unanswered) EMULATE_APP_DATA(chan_caller, 1, "Dial", "CDRTestChannel/Bob"); chan_callee = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "200", NULL, NULL, ast_channel_linkedid(chan_caller), 0, CHANNEL_TECH_NAME "/Bob"); + ast_channel_unlock(chan_callee); ast_set_flag(ast_channel_flags(chan_callee), AST_FLAG_OUTGOING); EMULATE_APP_DATA(chan_callee, 0, "AppDial", "(Outgoing Line)"); @@ -1194,6 +1200,7 @@ AST_TEST_DEFINE(test_cdr_dial_busy) EMULATE_APP_DATA(chan_caller, 1, "Dial", CHANNEL_TECH_NAME "/Bob"); chan_callee = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "200", NULL, NULL, ast_channel_linkedid(chan_caller), 0, CHANNEL_TECH_NAME "/Bob"); + ast_channel_unlock(chan_callee); ast_set_flag(ast_channel_flags(chan_callee), AST_FLAG_OUTGOING); EMULATE_APP_DATA(chan_callee, 0, "AppDial", "(Outgoing Line)"); @@ -1254,6 +1261,7 @@ AST_TEST_DEFINE(test_cdr_dial_congestion) EMULATE_APP_DATA(chan_caller, 1, "Dial", CHANNEL_TECH_NAME "/Bob"); chan_callee = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "200", NULL, NULL, ast_channel_linkedid(chan_caller), 0, CHANNEL_TECH_NAME "/Bob"); + ast_channel_unlock(chan_callee); ast_set_flag(ast_channel_flags(chan_callee), AST_FLAG_OUTGOING); EMULATE_APP_DATA(chan_callee, 0, "AppDial", "(Outgoing Line)"); @@ -1314,6 +1322,7 @@ AST_TEST_DEFINE(test_cdr_dial_unavailable) EMULATE_APP_DATA(chan_caller, 1, "Dial", CHANNEL_TECH_NAME "/Bob"); chan_callee = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "200", NULL, NULL, ast_channel_linkedid(chan_caller), 0, CHANNEL_TECH_NAME "/Bob"); + ast_channel_unlock(chan_callee); ast_set_flag(ast_channel_flags(chan_callee), AST_FLAG_OUTGOING); EMULATE_APP_DATA(chan_callee, 0, "AppDial", "(Outgoing Line)"); @@ -1375,6 +1384,7 @@ AST_TEST_DEFINE(test_cdr_dial_caller_cancel) EMULATE_APP_DATA(chan_caller, 1, "Dial", CHANNEL_TECH_NAME "/Bob"); chan_callee = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "200", NULL, NULL, ast_channel_linkedid(chan_caller), 0, CHANNEL_TECH_NAME "/Bob"); + ast_channel_unlock(chan_callee); ast_set_flag(ast_channel_flags(chan_callee), AST_FLAG_OUTGOING); EMULATE_APP_DATA(chan_callee, 0, "AppDial", "(Outgoing Line)"); @@ -1476,14 +1486,17 @@ AST_TEST_DEFINE(test_cdr_dial_parallel_failed) /* Outbound channels are created */ chan_bob = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "200", NULL, NULL, ast_channel_linkedid(chan_caller), 0, CHANNEL_TECH_NAME "/Bob"); + ast_channel_unlock(chan_bob); ast_set_flag(ast_channel_flags(chan_bob), AST_FLAG_OUTGOING); EMULATE_APP_DATA(chan_bob, 0, "AppDial", "(Outgoing Line)"); chan_charlie = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "300", NULL, NULL, ast_channel_linkedid(chan_caller), 0, CHANNEL_TECH_NAME "/Charlie"); + ast_channel_unlock(chan_charlie); ast_set_flag(ast_channel_flags(chan_charlie), AST_FLAG_OUTGOING); EMULATE_APP_DATA(chan_charlie, 0, "AppDial", "(Outgoing Line)"); chan_david = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "400", NULL, NULL, ast_channel_linkedid(chan_caller), 0, CHANNEL_TECH_NAME "/David"); + ast_channel_unlock(chan_david); ast_set_flag(ast_channel_flags(chan_david), AST_FLAG_OUTGOING); EMULATE_APP_DATA(chan_david, 0, "AppDial", "(Outgoing Line)"); @@ -1589,6 +1602,7 @@ AST_TEST_DEFINE(test_cdr_dial_answer_no_bridge) EMULATE_APP_DATA(chan_caller, 1, "Dial", CHANNEL_TECH_NAME "/Bob"); chan_callee = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "200", NULL, NULL, ast_channel_linkedid(chan_caller), 0, CHANNEL_TECH_NAME "/Bob"); + ast_channel_unlock(chan_callee); ast_set_flag(ast_channel_flags(chan_callee), AST_FLAG_OUTGOING); COPY_IDS(chan_callee, &bob_expected_one); @@ -1656,6 +1670,7 @@ AST_TEST_DEFINE(test_cdr_dial_answer_twoparty_bridge_a) EMULATE_APP_DATA(chan_caller, 1, "Dial", CHANNEL_TECH_NAME "/Bob"); chan_callee = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "200", NULL, NULL, ast_channel_linkedid(chan_caller), 0, CHANNEL_TECH_NAME "/Bob"); + ast_channel_unlock(chan_callee); ast_set_flag(ast_channel_flags(chan_callee), AST_FLAG_OUTGOING); EMULATE_APP_DATA(chan_callee, 0, "AppDial", "(Outgoing Line)"); @@ -1731,6 +1746,7 @@ AST_TEST_DEFINE(test_cdr_dial_answer_twoparty_bridge_b) EMULATE_APP_DATA(chan_caller, 1, "Dial", CHANNEL_TECH_NAME "/Bob"); chan_callee = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "200", NULL, NULL, ast_channel_linkedid(chan_caller), 0, CHANNEL_TECH_NAME "/Bob"); + ast_channel_unlock(chan_callee); ast_set_flag(ast_channel_flags(chan_callee), AST_FLAG_OUTGOING); EMULATE_APP_DATA(chan_callee, 0, "AppDial", "(Outgoing Line)"); @@ -1889,6 +1905,7 @@ AST_TEST_DEFINE(test_cdr_dial_answer_multiparty) EMULATE_APP_DATA(chan_alice, 1, "Dial", CHANNEL_TECH_NAME "/Bob"); chan_bob = ast_channel_alloc(0, AST_STATE_DOWN, "200", "Bob", "200", "200", "default", NULL, 0, CHANNEL_TECH_NAME "/Bob"); + ast_channel_unlock(chan_bob); ast_set_flag(ast_channel_flags(chan_bob), AST_FLAG_OUTGOING); EMULATE_APP_DATA(chan_bob, 0, "AppDial", "(Outgoing Line)"); ast_copy_string(bob_expected_one.uniqueid, ast_channel_uniqueid(chan_bob), sizeof(bob_expected_one.uniqueid)); @@ -1902,6 +1919,7 @@ AST_TEST_DEFINE(test_cdr_dial_answer_multiparty) ast_copy_string(charlie_expected_two.linkedid, ast_channel_linkedid(chan_alice), sizeof(charlie_expected_two.linkedid)); chan_david = ast_channel_alloc(0, AST_STATE_DOWN, "400", "David", "400", "400", "default", NULL, 0, CHANNEL_TECH_NAME "/David"); + ast_channel_unlock(chan_david); ast_set_flag(ast_channel_flags(chan_david), AST_FLAG_OUTGOING); EMULATE_APP_DATA(chan_david, 0, "AppDial", "(Outgoing Line)"); diff --git a/tests/test_cel.c b/tests/test_cel.c index 7732f3e9dd..7da4f9ee83 100644 --- a/tests/test_cel.c +++ b/tests/test_cel.c @@ -201,24 +201,28 @@ static void do_sleep(void) #define CREATE_ALICE_CHANNEL(channel_var, caller_id) do { \ (channel_var) = ast_channel_alloc(0, AST_STATE_DOWN, (caller_id)->id.number.str, (caller_id)->id.name.str, "100", "100", "default", NULL, 0, CHANNEL_TECH_NAME "/Alice"); \ APPEND_EVENT(channel_var, AST_CEL_CHANNEL_START, NULL, NULL); \ + ast_channel_unlock((channel_var)); \ } while (0) /*! \brief Create a \ref test_cel_chan_tech for Bob. */ #define CREATE_BOB_CHANNEL(channel_var, caller_id) do { \ (channel_var) = ast_channel_alloc(0, AST_STATE_DOWN, (caller_id)->id.number.str, (caller_id)->id.name.str, "200", "200", "default", NULL, 0, CHANNEL_TECH_NAME "/Bob"); \ APPEND_EVENT(channel_var, AST_CEL_CHANNEL_START, NULL, NULL); \ + ast_channel_unlock((channel_var)); \ } while (0) /*! \brief Create a \ref test_cel_chan_tech for Charlie. */ #define CREATE_CHARLIE_CHANNEL(channel_var, caller_id) do { \ (channel_var) = ast_channel_alloc(0, AST_STATE_DOWN, (caller_id)->id.number.str, (caller_id)->id.name.str, "300", "300", "default", NULL, 0, CHANNEL_TECH_NAME "/Charlie"); \ APPEND_EVENT(channel_var, AST_CEL_CHANNEL_START, NULL, NULL); \ + ast_channel_unlock((channel_var)); \ } while (0) /*! \brief Create a \ref test_cel_chan_tech for David. */ #define CREATE_DAVID_CHANNEL(channel_var, caller_id) do { \ (channel_var) = ast_channel_alloc(0, AST_STATE_DOWN, (caller_id)->id.number.str, (caller_id)->id.name.str, "400", "400", "default", NULL, 0, CHANNEL_TECH_NAME "/David"); \ APPEND_EVENT(channel_var, AST_CEL_CHANNEL_START, NULL, NULL); \ + ast_channel_unlock((channel_var)); \ } while (0) /*! \brief Emulate a channel entering into an application */ @@ -717,6 +721,7 @@ AST_TEST_DEFINE(test_cel_single_multiparty_bridge) #define START_DIALED_FULL(caller, callee, number, name) do { \ callee = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, number, NULL, NULL, ast_channel_linkedid(caller), 0, CHANNEL_TECH_NAME "/" name); \ + ast_channel_unlock(callee); \ if (append_expected_event(callee, AST_CEL_CHANNEL_START, NULL, NULL, NULL)) { \ return AST_TEST_FAIL; \ } \ diff --git a/tests/test_stasis_channels.c b/tests/test_stasis_channels.c index 45f1e2ba35..de445458c9 100644 --- a/tests/test_stasis_channels.c +++ b/tests/test_stasis_channels.c @@ -73,6 +73,7 @@ AST_TEST_DEFINE(channel_blob_create) type = stasis_message_type_create("test-type", NULL); chan = ast_channel_alloc(0, AST_STATE_DOWN, "100", "Alice", "100", "100", "default", NULL, 0, "TEST/Alice"); + ast_channel_unlock(chan); json = ast_json_pack("{s: s}", "foo", "bar"); @@ -125,6 +126,7 @@ AST_TEST_DEFINE(null_blob) type = stasis_message_type_create("test-type", NULL); chan = ast_channel_alloc(0, AST_STATE_DOWN, "100", "Alice", "100", "100", "default", NULL, 0, "TEST/Alice"); + ast_channel_unlock(chan); json = ast_json_pack("{s: s}", "foo", "bar"); @@ -192,8 +194,11 @@ AST_TEST_DEFINE(multi_channel_blob_snapshots) json = ast_json_pack("{s: s}", "type", "test"); chan_alice = ast_channel_alloc(0, AST_STATE_DOWN, "100", "Alice", "100", "100", "default", NULL, 0, "TEST/Alice"); + ast_channel_unlock(chan_alice); chan_bob = ast_channel_alloc(0, AST_STATE_DOWN, "200", "Bob", "200", "200", "default", NULL, 0, "TEST/Bob"); + ast_channel_unlock(chan_bob); chan_charlie = ast_channel_alloc(0, AST_STATE_DOWN, "300", "Bob", "300", "300", "default", NULL, 0, "TEST/Charlie"); + ast_channel_unlock(chan_charlie); blob = ast_multi_channel_blob_create(json); ast_multi_channel_blob_add_channel(blob, "Caller", ast_channel_snapshot_create(chan_alice)); @@ -251,6 +256,7 @@ AST_TEST_DEFINE(channel_snapshot_json) ast_test_validate(test, NULL == ast_channel_snapshot_to_json(NULL, NULL)); chan = ast_channel_alloc(0, AST_STATE_DOWN, "cid_num", "cid_name", "acctcode", "exten", "context", NULL, 0, "TEST/name"); + ast_channel_unlock(chan); ast_test_validate(test, NULL != chan); snapshot = ast_channel_snapshot_create(chan); ast_test_validate(test, NULL != snapshot); diff --git a/tests/test_substitution.c b/tests/test_substitution.c index 0fa0a584ea..4f87aebd97 100644 --- a/tests/test_substitution.c +++ b/tests/test_substitution.c @@ -244,6 +244,7 @@ AST_TEST_DEFINE(test_substitution) ast_test_status_update(test, "Testing variable substitution ...\n"); c = ast_channel_alloc(0, 0, "", "", "", "", "", "", 0, "Test/substitution"); + ast_channel_unlock(c); #define TEST(t) if (t == AST_TEST_FAIL) { res = AST_TEST_FAIL; } #if 0 diff --git a/tests/test_voicemail_api.c b/tests/test_voicemail_api.c index 01efeeec2d..b21ab1f87b 100644 --- a/tests/test_voicemail_api.c +++ b/tests/test_voicemail_api.c @@ -833,6 +833,8 @@ static struct ast_channel *test_vm_api_create_mock_channel(void) ast_format_set(ast_channel_rawreadformat(mock_channel), AST_FORMAT_GSM, 0); ast_channel_tech_set(mock_channel, &mock_channel_tech); + ast_channel_unlock(mock_channel); + return mock_channel; } -- GitLab