channels: Return allocated channels locked.
authorJoshua Colp <jcolp@digium.com>
Wed, 18 Dec 2013 19:28:05 +0000 (19:28 +0000)
committerJoshua Colp <jcolp@digium.com>
Wed, 18 Dec 2013 19:28:05 +0000 (19:28 +0000)
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

38 files changed:
addons/chan_mobile.c
addons/chan_ooh323.c
apps/app_meetme.c
apps/app_voicemail.c
apps/confbridge/conf_chan_record.c
channels/chan_alsa.c
channels/chan_console.c
channels/chan_dahdi.c
channels/chan_gtalk.c
channels/chan_h323.c
channels/chan_iax2.c
channels/chan_jingle.c
channels/chan_mgcp.c
channels/chan_misdn.c
channels/chan_motif.c
channels/chan_multicast_rtp.c
channels/chan_nbs.c
channels/chan_oss.c
channels/chan_phone.c
channels/chan_pjsip.c
channels/chan_sip.c
channels/chan_skinny.c
channels/chan_unistim.c
channels/chan_vpb.cc
include/asterisk/channel.h
main/channel.c
main/core_unreal.c
main/message.c
main/pbx.c
res/parking/parking_tests.c
res/res_calendar.c
res/res_stasis_snoop.c
tests/test_app.c
tests/test_cdr.c
tests/test_cel.c
tests/test_stasis_channels.c
tests/test_substitution.c
tests/test_voicemail_api.c

index 2cf7c7d..a76d778 100644 (file)
@@ -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:
index ff0a030..d89e00c 100644 (file)
@@ -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)
index ffd55e7..feea3b6 100644 (file)
@@ -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");
index dbcd283..4dffbbe 100644 (file)
@@ -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))) {
index 7080d11..78d1f27 100644 (file)
@@ -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;
 }
 
index 60bbacb..1d2d5f9 100644 (file)
@@ -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));
index 922c53b..e37b565 100644 (file)
@@ -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);
index 2eba958..636d886 100644 (file)
@@ -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);
index d6a0949..bec4401 100644 (file)
@@ -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);
index 22dba3c..1c9bb2a 100644 (file)
@@ -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));
index 84a72c8..b89ae82 100644 (file)
@@ -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));
index 56c15b1..c1c5026 100644 (file)
@@ -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);
index 84fb3b2..a6f75e6 100644 (file)
@@ -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));
index 38197c6..6dd9adf 100644 (file)
@@ -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);
index 1e7ee3c..2c2b270 100644 (file)
@@ -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;
 }
 
index 1b9e4d3..e3d8f9b 100644 (file)
@@ -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:
index 1d8c59d..7cce241 100644 (file)
@@ -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));
index 5ae18f3..3a52ac9 100644 (file)
@@ -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));
index c1a24b8..ba14a43 100644 (file)
@@ -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);
index 21a79f0..cd209d2 100644 (file)
@@ -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;
 }
index a764912..0fde84e 100644 (file)
@@ -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);
index a65862f..bb270d6 100644 (file)
@@ -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));
index 547cd7c..21bbbc1 100644 (file)
@@ -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");
index 12f2724..39d78cc 100644 (file)
@@ -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;
index 03d9aef..51530a8 100644 (file)
@@ -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, \
index d669baf..418e6a7 100644 (file)
@@ -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);
 
        /*
index 7e457f4..7ab7da7 100644 (file)
@@ -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;
 }
index ef2c97f..7690e4a 100644 (file)
@@ -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);
index 6b9bd5e..726677f 100644 (file)
@@ -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);
index e046ca8..f676776 100644 (file)
@@ -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;
 }
 
index eebd7b4..c36e5cf 100644 (file)
@@ -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;
index 1a40112..65186d1 100644 (file)
@@ -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 */
index f47b052..92da420 100644 (file)
@@ -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);
index 6d1626b..e70a064 100644 (file)
@@ -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)");
 
index 7732f3e..7da4f9e 100644 (file)
@@ -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; \
        } \
index 45f1e2b..de44545 100644 (file)
@@ -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);
index 0fa0a58..4f87aeb 100644 (file)
@@ -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
index 01efeee..b21ab1f 100644 (file)
@@ -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;
 }