channel locking: Add locking for channel snapshot creation
authorKevin Harwell <kharwell@digium.com>
Wed, 18 Dec 2013 20:33:37 +0000 (20:33 +0000)
committerKevin Harwell <kharwell@digium.com>
Wed, 18 Dec 2013 20:33:37 +0000 (20:33 +0000)
Original commit message by mmichelson (asterisk 12 r403311):

"This adds channel locks around calls to create channel snapshots as well
as other functions which operate on a channel and then end up
creating a channel snapshot. Functions that expect the channel to be
locked prior to being called have had their documentation updated to
indicate such."

The above was initially committed and then reverted at r403398.  The problem
was found to be in core_local.c in the publish_local_bridge_message function.
The ast_unreal_lock_all function locks and adds a reference to the returned
channels and while they were being unlocked they were not being unreffed when
no longer needed.  Fixed by unreffing the channels.

Also in bridge.c a lock was obtained on "other->chan", but then an attempt was
made to unlock "other" and not the previously locked channel.  Fixed by
unlocking "other->chan"

(closes issue ASTERISK-22709)
Reported by: John Bigelow
........

Merged revisions 404237 from http://svn.asterisk.org/svn/asterisk/branches/12

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@404260 65c4cc65-6c06-0410-ace0-fbb531ad65f3

53 files changed:
addons/chan_mobile.c
addons/chan_ooh323.c
apps/app_agent_pool.c
apps/app_confbridge.c
apps/app_dial.c
apps/app_disa.c
apps/app_meetme.c
apps/app_queue.c
apps/app_userevent.c
apps/app_voicemail.c
channels/chan_alsa.c
channels/chan_console.c
channels/chan_dahdi.c
channels/chan_gtalk.c
channels/chan_iax2.c
channels/chan_jingle.c
channels/chan_mgcp.c
channels/chan_misdn.c
channels/chan_motif.c
channels/chan_oss.c
channels/chan_phone.c
channels/chan_pjsip.c
channels/chan_skinny.c
channels/chan_unistim.c
channels/chan_vpb.cc
channels/sig_analog.c
channels/sig_pri.c
funcs/func_timeout.c
include/asterisk/aoc.h
include/asterisk/channel.h
include/asterisk/channelstate.h
include/asterisk/stasis_bridges.h
include/asterisk/stasis_channels.h
main/bridge.c
main/bridge_channel.c
main/cel.c
main/channel.c
main/core_local.c
main/dial.c
main/endpoints.c
main/pbx.c
main/pickup.c
main/stasis_bridges.c
main/stasis_channels.c
pbx/pbx_realtime.c
res/parking/parking_bridge_features.c
res/parking/parking_manager.c
res/res_agi.c
res/res_pjsip_refer.c
res/res_stasis.c
tests/test_cdr.c
tests/test_cel.c
tests/test_stasis_channels.c

index a76d778..197974a 100644 (file)
@@ -878,7 +878,6 @@ static struct ast_channel *mbl_new(int state, struct mbl_pvt *pvt, char *cid_num
        if (pvt->sco_socket != -1) {
                ast_channel_set_fd(chn, 0, pvt->sco_socket);
        }
-
        ast_channel_unlock(chn);
 
        return chn;
index 3aea0d4..8111b71 100644 (file)
@@ -2164,8 +2164,8 @@ int onCallEstablished(ooCallData *call)
                        }
 
                        ast_queue_control(c, AST_CONTROL_ANSWER);
-                       ast_channel_unlock(p->owner);
                        ast_publish_channel_state(c);
+                       ast_channel_unlock(p->owner);
                }
                ast_mutex_unlock(&p->lock);
 
index 2b0d1f8..a44c75d 100644 (file)
@@ -1465,7 +1465,9 @@ static void agent_logout(struct agent_pvt *agent)
                ast_bridge_destroy(caller_bridge, AST_CAUSE_USER_BUSY);
        }
 
+       ast_channel_lock(logged);
        send_agent_logoff(logged, agent->username, time_logged_in);
+       ast_channel_unlock(logged);
        ast_verb(2, "Agent '%s' logged out.  Logged in for %ld seconds.\n",
                agent->username, time_logged_in);
        ast_channel_unref(logged);
@@ -2046,7 +2048,9 @@ static int agent_login_exec(struct ast_channel *chan, const char *data)
        ast_verb(2, "Agent '%s' logged in (format %s/%s)\n", agent->username,
                ast_getformatname(ast_channel_readformat(chan)),
                ast_getformatname(ast_channel_writeformat(chan)));
+       ast_channel_lock(chan);
        send_agent_login(chan, agent->username);
+       ast_channel_unlock(chan);
 
        agent_run(agent, chan);
        return -1;
index 300d2c7..01ae425 100644 (file)
@@ -1379,7 +1379,9 @@ static int alloc_playback_chan(struct confbridge_conference *conference)
        }
 
        /* To make sure playback_chan has the same language of that profile */
+       ast_channel_lock(conference->playback_chan);
        ast_channel_language_set(conference->playback_chan, conference->b_profile.language);
+       ast_channel_unlock(conference->playback_chan);
 
        ast_debug(1, "Created announcer channel '%s' to conference bridge '%s'\n",
                ast_channel_name(conference->playback_chan), conference->name);
index fdbe056..99d00f1 100644 (file)
@@ -2104,6 +2104,7 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
        struct ast_party_caller caller;
 
        /* Reset all DIAL variables back to blank, to prevent confusion (in case we don't reset all of them). */
+       ast_channel_lock(chan);
        ast_channel_stage_snapshot(chan);
        pbx_builtin_setvar_helper(chan, "DIALSTATUS", "");
        pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", "");
@@ -2111,6 +2112,7 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
        pbx_builtin_setvar_helper(chan, "ANSWEREDTIME", "");
        pbx_builtin_setvar_helper(chan, "DIALEDTIME", "");
        ast_channel_stage_snapshot_done(chan);
+       ast_channel_unlock(chan);
 
        if (ast_strlen_zero(data)) {
                ast_log(LOG_WARNING, "Dial requires an argument (technology/resource)\n");
@@ -2443,15 +2445,17 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
                        continue;
                }
 
+               ast_channel_lock(tc);
                ast_channel_stage_snapshot(tc);
+               ast_channel_unlock(tc);
 
                ast_channel_get_device_name(tc, device_name, sizeof(device_name));
                if (!ignore_cc) {
                        ast_cc_extension_monitor_add_dialstring(chan, tmp->interface, device_name);
                }
-               pbx_builtin_setvar_helper(tc, "DIALEDPEERNUMBER", tmp->number);
 
                ast_channel_lock_both(tc, chan);
+               pbx_builtin_setvar_helper(tc, "DIALEDPEERNUMBER", tmp->number);
 
                /* Setup outgoing SDP to match incoming one */
                if (!AST_LIST_FIRST(&out_chans) && !rest && CAN_EARLY_BRIDGE(peerflags, chan, tc)) {
@@ -2724,8 +2728,10 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
                        number = ast_strdupa(number);
                }
                ast_channel_unlock(peer);
+               ast_channel_lock(chan);
                pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", number);
                ast_channel_stage_snapshot_done(chan);
+               ast_channel_unlock(chan);
 
                if (!ast_strlen_zero(args.url) && ast_channel_supports_html(peer) ) {
                        ast_debug(1, "app_dial: sendurl=%s.\n", args.url);
@@ -2811,16 +2817,18 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
                        /* chan and peer are going into the PBX; as such neither are considered
                         * outgoing channels any longer */
                        ast_clear_flag(ast_channel_flags(chan), AST_FLAG_OUTGOING);
-                       ast_channel_stage_snapshot(peer);
-                       ast_clear_flag(ast_channel_flags(peer), AST_FLAG_OUTGOING);
 
                        ast_replace_subargument_delimiter(opt_args[OPT_ARG_GOTO]);
                        ast_parseable_goto(chan, opt_args[OPT_ARG_GOTO]);
                        /* peer goes to the same context and extension as chan, so just copy info from chan*/
+                       ast_channel_lock(peer);
+                       ast_channel_stage_snapshot(peer);
+                       ast_clear_flag(ast_channel_flags(peer), AST_FLAG_OUTGOING);
                        ast_channel_context_set(peer, ast_channel_context(chan));
                        ast_channel_exten_set(peer, ast_channel_exten(chan));
                        ast_channel_priority_set(peer, ast_channel_priority(chan) + 2);
                        ast_channel_stage_snapshot_done(peer);
+                       ast_channel_unlock(peer);
                        if (ast_pbx_start(peer)) {
                                ast_autoservice_chan_hangup_peer(chan, peer);
                        }
@@ -2970,7 +2978,9 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
                if (!res) {
                        if (!ast_tvzero(calldurationlimit)) {
                                struct timeval whentohangup = ast_tvadd(ast_tvnow(), calldurationlimit);
+                               ast_channel_lock(peer);
                                ast_channel_whentohangup_set(peer, &whentohangup);
+                               ast_channel_unlock(peer);
                        }
                        if (!ast_strlen_zero(dtmfcalled)) {
                                ast_verb(3, "Sending DTMF '%s' to the called party.\n", dtmfcalled);
index fe53772..9e74127 100644 (file)
@@ -381,8 +381,11 @@ static int disa_exec(struct ast_channel *chan, const char *data)
                                ast_set_callerid(chan, ourcidnum, ourcidname, ourcidnum);
                        }
 
-                       if (!ast_strlen_zero(acctcode))
+                       if (!ast_strlen_zero(acctcode)) {
+                               ast_channel_lock(chan);
                                ast_channel_accountcode_set(chan, acctcode);
+                               ast_channel_unlock(chan);
+                       }
 
                        if (special_noanswer) {
                                ast_clear_flag(&cdr_flags, AST_CDR_FLAG_DISABLE);
index feea3b6..4621d15 100644 (file)
@@ -1384,7 +1384,9 @@ static void meetme_stasis_generate_msg(struct ast_conference *meetme_conference,
                }
        }
 
+       ast_channel_lock(chan);
        msg = ast_channel_blob_create(chan, message_type, json_object);
+       ast_channel_unlock(chan);
 
        if (!msg) {
                return;
index d9f0f85..e1c8a00 100644 (file)
@@ -2040,8 +2040,12 @@ static void queue_publish_multi_channel_blob(struct ast_channel *caller, struct
        RAII_VAR(struct ast_channel_snapshot *, caller_snapshot, NULL, ao2_cleanup);
        RAII_VAR(struct ast_channel_snapshot *, agent_snapshot, NULL, ao2_cleanup);
 
+       ast_channel_lock(caller);
        caller_snapshot = ast_channel_snapshot_create(caller);
+       ast_channel_unlock(caller);
+       ast_channel_lock(agent);
        agent_snapshot = ast_channel_snapshot_create(agent);
+       ast_channel_unlock(agent);
 
        if (!caller_snapshot || !agent_snapshot) {
                return;
@@ -3452,7 +3456,9 @@ static int join_queue(char *queuename, struct queue_ent *qe, enum queue_result *
                                     "Queue", q->name,
                                     "Position", qe->pos,
                                     "Count", q->count);
+               ast_channel_lock(qe->chan);
                ast_channel_publish_blob(qe->chan, queue_caller_join_type(), blob);
+               ast_channel_unlock(qe->chan);
                ast_debug(1, "Queue '%s' Join, Channel '%s', Position '%d'\n", q->name, ast_channel_name(qe->chan), qe->pos );
        }
        ao2_unlock(q);
@@ -3731,7 +3737,9 @@ static void leave_queue(struct queue_ent *qe)
                                             "Queue", q->name,
                                             "Position", qe->pos,
                                             "Count", q->count);
+                       ast_channel_lock(qe->chan);
                        ast_channel_publish_blob(qe->chan, queue_caller_leave_type(), blob);
+                       ast_channel_unlock(qe->chan);
                        ast_debug(1, "Queue '%s' Leave, Channel '%s'\n", q->name, ast_channel_name(qe->chan));
                        /* Take us out of the queue */
                        if (prev) {
@@ -4329,10 +4337,13 @@ static void record_abandoned(struct queue_ent *qe)
                             "Position", qe->pos,
                             "OriginalPosition", qe->opos,
                             "HoldTime", (int)(time(NULL) - qe->start));
-       ast_channel_publish_blob(qe->chan, queue_caller_abandon_type(), blob);
 
        qe->parent->callsabandoned++;
        ao2_unlock(qe->parent);
+
+       ast_channel_lock(qe->chan);
+       ast_channel_publish_blob(qe->chan, queue_caller_abandon_type(), blob);
+       ast_channel_unlock(qe->chan);
 }
 
 /*! \brief RNA == Ring No Answer. Common code that is executed when we try a queue member and they don't answer. */
index e0dafbb..f5defd4 100644 (file)
@@ -114,7 +114,9 @@ static int userevent_exec(struct ast_channel *chan, const char *data)
                }
        }
 
+       ast_channel_lock(chan);
        ast_channel_publish_blob(chan, ast_channel_user_event_type(), blob);
+       ast_channel_unlock(chan);
        return 0;
 }
 
index 4dffbbe..3669298 100644 (file)
@@ -10958,8 +10958,11 @@ static int vm_execmain(struct ast_channel *chan, const char *data)
 #endif
 
        /* Set language from config to override channel language */
-       if (!ast_strlen_zero(vmu->language))
+       if (!ast_strlen_zero(vmu->language)) {
+               ast_channel_lock(chan);
                ast_channel_language_set(chan, vmu->language);
+               ast_channel_unlock(chan);
+       }
 
        /* Retrieve urgent, old and new message counts */
        ast_debug(1, "Before open_mailbox\n");
index 1d2d5f9..a68a0b2 100644 (file)
@@ -601,7 +601,6 @@ static struct ast_channel *alsa_new(struct chan_alsa_pvt *p, int state, const ch
        ast_jb_configure(tmp, &global_jbconf);
 
        ast_channel_stage_snapshot_done(tmp);
-
        ast_channel_unlock(tmp);
 
        if (state != AST_STATE_DOWN) {
index e37b565..083af7c 100644 (file)
@@ -444,7 +444,6 @@ static struct ast_channel *console_new(struct console_pvt *pvt, const char *ext,
        ast_jb_configure(chan, &global_jbconf);
 
        ast_channel_stage_snapshot_done(chan);
-
        ast_channel_unlock(chan);
 
        if (state != AST_STATE_DOWN) {
index 636d886..e4f1c0c 100644 (file)
@@ -1667,7 +1667,9 @@ static void publish_dahdichannel(struct ast_channel *chan, int span, const char
                return;
        }
 
+       ast_channel_lock(chan);
        ast_channel_publish_blob(chan, dahdichannel_type(), blob);
+       ast_channel_unlock(chan);
 }
 
 /*!
@@ -9616,6 +9618,7 @@ static void *analog_ss_thread(void *data)
                                                getforward = 0;
                                        } else {
                                                res = tone_zone_play_tone(p->subs[idx].dfd, -1);
+                                               ast_channel_lock(chan);
                                                ast_channel_exten_set(chan, exten);
                                                if (!ast_strlen_zero(p->cid_num)) {
                                                        if (!p->hidecallerid)
@@ -9628,6 +9631,7 @@ static void *analog_ss_thread(void *data)
                                                                ast_set_callerid(chan, NULL, p->cid_name, NULL);
                                                }
                                                ast_setstate(chan, AST_STATE_RING);
+                                               ast_channel_unlock(chan);
                                                dahdi_ec_enable(p);
                                                res = ast_pbx_run(chan);
                                                if (res) {
@@ -10391,8 +10395,10 @@ static void *analog_ss_thread(void *data)
 
                my_handle_notify_message(chan, p, flags, -1);
 
+               ast_channel_lock(chan);
                ast_setstate(chan, AST_STATE_RING);
                ast_channel_rings_set(chan, 1);
+               ast_channel_unlock(chan);
                p->ringt = p->ringt_base;
                res = ast_pbx_run(chan);
                if (res) {
index bec4401..60213d3 100644 (file)
@@ -1226,7 +1226,6 @@ static struct ast_channel *gtalk_new(struct gtalk *client, struct gtalk_pvt *i,
                ast_jb_configure(tmp, &global_jbconf);
 
        ast_channel_stage_snapshot_done(tmp);
-
        ast_channel_unlock(tmp);
 
        if (state != AST_STATE_DOWN && ast_pbx_start(tmp)) {
@@ -1421,7 +1420,9 @@ static int gtalk_newcall(struct gtalk *client, ikspak *pak)
        ast_format_cap_joint_copy(p->cap, p->peercap, p->jointcap);
        ast_mutex_unlock(&p->lock);
 
+       ast_channel_lock(chan);
        ast_setstate(chan, AST_STATE_RING);
+       ast_channel_unlock(chan);
        if (ast_format_cap_is_empty(p->jointcap)) {
                ast_log(LOG_WARNING, "Capabilities don't match : us - %s, peer - %s, combined - %s \n", ast_getformatname_multiple(s1, BUFSIZ, p->cap),
                        ast_getformatname_multiple(s2, BUFSIZ, p->peercap),
index b89ae82..447860b 100644 (file)
@@ -5804,7 +5804,6 @@ 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) {
@@ -12237,7 +12236,9 @@ static struct ast_channel *iax2_request(const char *type, struct ast_format_cap
        if (c) {
                struct ast_format_cap *joint;
                if (callid) {
+                       ast_channel_lock(c);
                        ast_channel_callid_set(c, callid);
+                       ast_channel_unlock(c);
                }
 
                /* Choose a format we can live with */
index c1c5026..410cb32 100644 (file)
@@ -941,7 +941,6 @@ static struct ast_channel *jingle_new(struct jingle *client, struct jingle_pvt *
                ast_jb_configure(tmp, &global_jbconf);
 
        ast_channel_stage_snapshot_done(tmp);
-
        ast_channel_unlock(tmp);
 
        if (state != AST_STATE_DOWN && ast_pbx_start(tmp)) {
@@ -1117,7 +1116,9 @@ static int jingle_newcall(struct jingle *client, ikspak *pak)
        }
 
        ast_mutex_unlock(&p->lock);
+       ast_channel_lock(chan);
        ast_setstate(chan, AST_STATE_RING);
+       ast_channel_unlock(chan);
        res = ast_pbx_start(chan);
        
        switch (res) {
index a6f75e6..aaed68f 100644 (file)
@@ -1570,7 +1570,6 @@ 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) {
@@ -3048,6 +3047,7 @@ static void *mgcp_ss(void *data)
                                } else {
                                        /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/
                                        ast_indicate(chan, -1);
+                                       ast_channel_lock(chan);
                                        ast_channel_exten_set(chan, p->dtmf_buf);
                                        ast_channel_dialed(chan)->number.str = ast_strdup(p->dtmf_buf);
                                        memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
@@ -3056,6 +3056,7 @@ static void *mgcp_ss(void *data)
                                                p->hidecallerid ? "" : p->cid_name,
                                                ast_channel_caller(chan)->ani.number.valid ? NULL : p->cid_num);
                                        ast_setstate(chan, AST_STATE_RING);
+                                       ast_channel_unlock(chan);
                                        if (p->dtmfmode & MGCP_DTMF_HYBRID) {
                                                p->dtmfmode |= MGCP_DTMF_INBAND;
                                                ast_indicate(chan, -1);
index 6dd9adf..02b5250 100644 (file)
@@ -5954,7 +5954,9 @@ static int read_config(struct chan_list *ch)
        chan_misdn_log(1, port, "read_config: Getting Config\n");
 
        misdn_cfg_get(port, MISDN_CFG_LANGUAGE, lang, sizeof(lang));
+       ast_channel_lock(ast);
        ast_channel_language_set(ast, lang);
+       ast_channel_unlock(ast);
 
        misdn_cfg_get(port, MISDN_CFG_MUSICCLASS, ch->mohinterpret, sizeof(ch->mohinterpret));
 
@@ -6000,7 +6002,9 @@ static int read_config(struct chan_list *ch)
 
        misdn_cfg_get(bc->port, MISDN_CFG_CONTEXT, ch->context, sizeof(ch->context));
 
+       ast_channel_lock(ast);
        ast_channel_context_set(ast, ch->context);
+       ast_channel_unlock(ast);
 
 #ifdef MISDN_1_2
        update_pipeline_config(bc);
@@ -6017,8 +6021,10 @@ static int read_config(struct chan_list *ch)
        misdn_cfg_get(port, MISDN_CFG_PICKUPGROUP, &pg, sizeof(pg));
        misdn_cfg_get(port, MISDN_CFG_CALLGROUP, &cg, sizeof(cg));
        chan_misdn_log(5, port, " --> * CallGrp:%s PickupGrp:%s\n", ast_print_group(buf, sizeof(buf), cg), ast_print_group(buf2, sizeof(buf2), pg));
+       ast_channel_lock(ast);
        ast_channel_pickupgroup_set(ast, pg);
        ast_channel_callgroup_set(ast, cg);
+       ast_channel_unlock(ast);
 
        misdn_cfg_get(port, MISDN_CFG_NAMEDPICKUPGROUP, &npg, sizeof(npg));
        misdn_cfg_get(port, MISDN_CFG_NAMEDCALLGROUP, &ncg, sizeof(ncg));
@@ -6031,8 +6037,10 @@ static int read_config(struct chan_list *ch)
                ast_free(tmp_str);
        }
 
+       ast_channel_lock(ast);
        ast_channel_named_pickupgroups_set(ast, npg);
        ast_channel_named_callgroups_set(ast, ncg);
+       ast_channel_unlock(ast);
 
        if (ch->originator == ORG_AST) {
                char callerid[BUFFERSIZE + 1];
@@ -6086,7 +6094,9 @@ static int read_config(struct chan_list *ch)
                /* Add configured prefix to dialed.number */
                misdn_add_number_prefix(bc->port, bc->dialed.number_type, bc->dialed.number, sizeof(bc->dialed.number));
 
+               ast_channel_lock(ast);
                ast_channel_exten_set(ast, bc->dialed.number);
+               ast_channel_unlock(ast);
 
                misdn_cfg_get(bc->port, MISDN_CFG_OVERLAP_DIAL, &ch->overlap_dial, sizeof(ch->overlap_dial));
                ast_mutex_init(&ch->overlap_tv_lock);
@@ -10232,8 +10242,10 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
 
                export_ch(chan, bc, ch);
 
+               ast_channel_lock(ch->ast);
                ast_channel_rings_set(ch->ast, 1);
                ast_setstate(ch->ast, AST_STATE_RINGING);
+               ast_channel_unlock(ch->ast);
 
                /* Update asterisk channel caller information */
                chan_misdn_log(2, bc->port, " --> TON: %s(%d)\n", misdn_to_str_ton(bc->caller.number_type), bc->caller.number_type);
@@ -10532,7 +10544,9 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
                }
 
                ast_queue_control(ch->ast, AST_CONTROL_RINGING);
+               ast_channel_lock(ch->ast);
                ast_setstate(ch->ast, AST_STATE_RINGING);
+               ast_channel_unlock(ch->ast);
 
                cb_log(7, bc->port, " --> Set State Ringing\n");
 
index 2c2b270..248f811 100644 (file)
@@ -852,7 +852,6 @@ static struct ast_channel *jingle_new(struct jingle_endpoint *endpoint, struct j
        ao2_unlock(endpoint);
 
        ast_channel_stage_snapshot_done(chan);
-
        ast_channel_unlock(chan);
 
        return chan;
@@ -2414,7 +2413,9 @@ static void jingle_action_session_initiate(struct jingle_endpoint *endpoint, str
 
        ao2_link(endpoint->state->sessions, session);
 
+       ast_channel_lock(chan);
        ast_setstate(chan, AST_STATE_RING);
+       ast_channel_unlock(chan);
        res = ast_pbx_start(chan);
 
        switch (res) {
index 3a52ac9..92c7374 100644 (file)
@@ -799,6 +799,7 @@ static struct ast_channel *oss_new(struct chan_oss_pvt *o, char *ext, char *ctx,
        c = ast_channel_alloc(1, state, o->cid_num, o->cid_name, "", ext, ctx, linkedid, 0, "Console/%s", o->device + 5);
        if (c == NULL)
                return NULL;
+       ast_channel_lock(c);
        ast_channel_tech_set(c, &oss_tech);
        if (o->sounddev < 0)
                setformat(o, O_RDWR);
index ba14a43..94a40ca 100644 (file)
@@ -862,6 +862,7 @@ static struct ast_channel *phone_new(struct phone_pvt *i, int state, char *cntx,
        struct ast_format tmpfmt;
        tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, "", i->ext, i->context, linkedid, 0, "Phone/%s", i->dev + 5);
        if (tmp) {
+               ast_channel_lock(tmp);
                ast_channel_tech_set(tmp, cur_tech);
                ast_channel_set_fd(tmp, 0, i->fd);
                /* XXX Switching formats silently causes kernel panics XXX */
index cd209d2..a560d77 100644 (file)
@@ -364,6 +364,7 @@ static struct ast_channel *chan_pjsip_new(struct ast_sip_session *session, int s
                return NULL;
        }
 
+
        ast_channel_stage_snapshot(chan);
 
        ast_channel_tech_pvt_set(chan, channel);
@@ -1835,9 +1836,11 @@ static void chan_pjsip_incoming_response(struct ast_sip_session *session, struct
        switch (status.code) {
        case 180:
                ast_queue_control(session->channel, AST_CONTROL_RINGING);
+               ast_channel_lock(session->channel);
                if (ast_channel_state(session->channel) != AST_STATE_UP) {
                        ast_setstate(session->channel, AST_STATE_RINGING);
                }
+               ast_channel_unlock(session->channel);
                break;
        case 183:
                ast_queue_control(session->channel, AST_CONTROL_PROGRESS);
index bb270d6..49f2c84 100644 (file)
@@ -4845,6 +4845,7 @@ static void *skinny_newcall(void *data)
        struct skinny_device *d = l->device;
        int res = 0;
 
+       ast_channel_lock(c);
        ast_set_callerid(c,
                l->hidecallerid ? "" : l->cid_num,
                l->hidecallerid ? "" : l->cid_name,
@@ -4858,6 +4859,7 @@ static void *skinny_newcall(void *data)
        ast_party_name_init(&ast_channel_connected(c)->id.name);
 #endif
        ast_setstate(c, AST_STATE_RING);
+       ast_channel_unlock(c);
        if (!sub->rtp) {
                start_rtp(sub);
        }
@@ -5501,7 +5503,6 @@ static struct ast_channel *skinny_new(struct skinny_line *l, struct skinny_subli
                        pbx_builtin_setvar_helper(tmp, v->name, v->value);
 
                ast_channel_stage_snapshot_done(tmp);
-
                ast_channel_unlock(tmp);
 
                if (state != AST_STATE_DOWN) {
index 21bbbc1..bc79f5e 100644 (file)
@@ -2517,10 +2517,12 @@ static void *unistim_ss(void *data)
        int res;
 
        ast_verb(3, "Starting switch on '%s@%s-%d' to %s\n", l->name, l->parent->name, sub->softkey, s->device->phone_number);
+       ast_channel_lock(chan);
        ast_channel_exten_set(chan, s->device->phone_number);
+       ast_setstate(chan, AST_STATE_RING);
+       ast_channel_unlock(chan);
        ast_copy_string(s->device->redial_number, s->device->phone_number,
                                        sizeof(s->device->redial_number));
-       ast_setstate(chan, AST_STATE_RING);
        res = ast_pbx_run(chan);
        if (res) {
                ast_log(LOG_WARNING, "PBX exited non-zero\n");
@@ -5627,7 +5629,6 @@ static struct ast_channel *unistim_new(struct unistim_subchannel *sub, int state
        ast_channel_priority_set(tmp, 1);
 
        ast_channel_stage_snapshot_done(tmp);
-
        ast_channel_unlock(tmp);
 
        if (state != AST_STATE_DOWN) {
index 39d78cc..5ea24cc 100644 (file)
@@ -2471,7 +2471,6 @@ static struct ast_channel *vpb_new(struct vpb_pvt *me, enum ast_channel_state st
                        ast_channel_exten_set(tmp, "s");
                if (!ast_strlen_zero(me->language))
                        ast_channel_language_set(tmp, me->language);
-
                ast_channel_unlock(tmp);
 
                me->owner = tmp;
index bbf7a3c..51d3f14 100644 (file)
@@ -2120,6 +2120,7 @@ static void *__analog_ss_thread(void *data)
                                                getforward = 0;
                                        } else {
                                                res = analog_play_tone(p, idx, -1);
+                                               ast_channel_lock(chan);
                                                ast_channel_exten_set(chan, exten);
                                                if (!ast_strlen_zero(p->cid_num)) {
                                                        if (!p->hidecallerid) {
@@ -2134,6 +2135,7 @@ static void *__analog_ss_thread(void *data)
                                                        }
                                                }
                                                ast_setstate(chan, AST_STATE_RING);
+                                               ast_channel_unlock(chan);
                                                analog_set_echocanceller(p, 1);
                                                res = ast_pbx_run(chan);
                                                if (res) {
@@ -2615,8 +2617,10 @@ static void *__analog_ss_thread(void *data)
 
                analog_handle_notify_message(chan, p, flags, -1);
 
+               ast_channel_lock(chan);
                ast_setstate(chan, AST_STATE_RING);
                ast_channel_rings_set(chan, 1);
+               ast_channel_unlock(chan);
                analog_set_ringtimeout(p, p->ringt_base);
                res = ast_pbx_run(chan);
                if (res) {
index 5def34c..48c8c33 100644 (file)
@@ -2160,7 +2160,9 @@ static void *pri_ss_thread(void *data)
 #endif /* defined(ISSUE_16789) */
 
                sig_pri_set_echocanceller(p, 1);
+               ast_channel_lock(chan);
                ast_setstate(chan, AST_STATE_RING);
+               ast_channel_unlock(chan);
                res = ast_pbx_run(chan);
                if (res) {
                        ast_log(LOG_WARNING, "PBX exited non-zero!\n");
index 3c2810f..e93ce3f 100644 (file)
@@ -155,7 +155,9 @@ static int timeout_write(struct ast_channel *chan, const char *cmd, char *data,
        switch (*data) {
        case 'a':
        case 'A':
+               ast_channel_lock(chan);
                ast_channel_setwhentohangup_tv(chan, when);
+               ast_channel_unlock(chan);
                if (!ast_tvzero(*ast_channel_whentohangup(chan))) {
                        when = ast_tvadd(when, ast_tvnow());
                        ast_strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S.%3q %Z",
index 727362c..171fbb3 100644 (file)
@@ -497,7 +497,10 @@ int ast_aoc_s_add_special_arrangement(struct ast_aoc_decoded *decoded,
  */
 int ast_aoc_decoded2str(const struct ast_aoc_decoded *decoded, struct ast_str **msg);
 
-/*! \brief generate AOC manager event for an AOC-S, AOC-D, or AOC-E msg */
+/*!
+ * \brief generate AOC manager event for an AOC-S, AOC-D, or AOC-E msg
+ * \pre chan is locked
+ */
 int ast_aoc_manager_event(const struct ast_aoc_decoded *decoded, struct ast_channel *chan);
 
 /*! \brief get the message type, AOC-D, AOC-E, or AOC Request */
index 51530a8..80ed745 100644 (file)
@@ -1538,8 +1538,7 @@ int ast_channel_cmpwhentohangup_tv(struct ast_channel *chan, struct timeval offs
  * \details
  * This function sets the absolute time out on a channel (when to hang up).
  *
- * \note This function does not require that the channel is locked before
- *       calling it.
+ * \pre chan is locked
  *
  * \return Nothing
  * \sa ast_channel_setwhentohangup_tv()
@@ -1555,8 +1554,7 @@ void ast_channel_setwhentohangup(struct ast_channel *chan, time_t offset) __attr
  *
  * This function sets the absolute time out on a channel (when to hang up).
  *
- * \note This function does not require that the channel is locked before
- * calling it.
+ * \pre chan is locked
  *
  * \return Nothing
  * \since 1.6.1
@@ -2340,6 +2338,8 @@ void ast_channel_inherit_variables(const struct ast_channel *parent, struct ast_
  * \param chan the channel
  * \param vars a linked list of variables
  *
+ * \pre chan is locked
+ *
  * \details
  * Variable names can be for a regular channel variable or a dialplan function
  * that has the ability to be written to.
@@ -3806,6 +3806,15 @@ void ast_channel_name_set(struct ast_channel *chan, const char *name);
        void ast_channel_##field##_build_va(struct ast_channel *chan, const char *fmt, va_list ap) __attribute__((format(printf, 2, 0))); \
        void ast_channel_##field##_build(struct ast_channel *chan, const char *fmt, ...) __attribute__((format(printf, 2, 3)))
 
+/*!
+ * The following string fields result in channel snapshot creation and
+ * should have the channel locked when called:
+ *
+ * \li language
+ * \li accountcode
+ * \li peeracccount
+ * \li linkedid
+ */
 DECLARE_STRINGFIELD_SETTERS_FOR(name);
 DECLARE_STRINGFIELD_SETTERS_FOR(language);
 DECLARE_STRINGFIELD_SETTERS_FOR(musicclass);
@@ -3857,6 +3866,10 @@ void ast_channel_sending_dtmf_digit_set(struct ast_channel *chan, char value);
 struct timeval ast_channel_sending_dtmf_tv(const struct ast_channel *chan);
 void ast_channel_sending_dtmf_tv_set(struct ast_channel *chan, struct timeval value);
 enum ama_flags ast_channel_amaflags(const struct ast_channel *chan);
+
+/*!
+ * \pre chan is locked
+ */
 void ast_channel_amaflags_set(struct ast_channel *chan, enum ama_flags value);
 int ast_channel_epfd(const struct ast_channel *chan);
 void ast_channel_epfd_set(struct ast_channel *chan, int value);
@@ -3940,6 +3953,10 @@ enum ast_channel_adsicpe ast_channel_adsicpe(const struct ast_channel *chan);
 void ast_channel_adsicpe_set(struct ast_channel *chan, enum ast_channel_adsicpe value);
 enum ast_channel_state ast_channel_state(const struct ast_channel *chan);
 struct ast_callid *ast_channel_callid(const struct ast_channel *chan);
+
+/*!
+ * \pre chan is locked
+ */
 void ast_channel_callid_set(struct ast_channel *chan, struct ast_callid *value);
 
 /* XXX Internal use only, make sure to move later */
@@ -3980,6 +3997,10 @@ void ast_channel_connected_set(struct ast_channel *chan, struct ast_party_connec
 void ast_channel_dialed_set(struct ast_channel *chan, struct ast_party_dialed *value);
 void ast_channel_redirecting_set(struct ast_channel *chan, struct ast_party_redirecting *value);
 void ast_channel_dtmf_tv_set(struct ast_channel *chan, struct timeval *value);
+
+/*!
+ * \pre chan is locked
+ */
 void ast_channel_whentohangup_set(struct ast_channel *chan, struct timeval *value);
 void ast_channel_varshead_set(struct ast_channel *chan, struct varshead *value);
 struct timeval ast_channel_creationtime(struct ast_channel *chan);
@@ -3995,8 +4016,14 @@ struct ast_readq_list *ast_channel_readq(struct ast_channel *chan);
 
 /* Typedef accessors */
 ast_group_t ast_channel_callgroup(const struct ast_channel *chan);
+/*!
+ * \pre chan is locked
+ */
 void ast_channel_callgroup_set(struct ast_channel *chan, ast_group_t value);
 ast_group_t ast_channel_pickupgroup(const struct ast_channel *chan);
+/*!
+ * \pre chan is locked
+ */
 void ast_channel_pickupgroup_set(struct ast_channel *chan, ast_group_t value);
 struct ast_namedgroups *ast_channel_named_callgroups(const struct ast_channel *chan);
 void ast_channel_named_callgroups_set(struct ast_channel *chan, struct ast_namedgroups *value);
@@ -4043,6 +4070,9 @@ ast_timing_func_t ast_channel_timingfunc(const struct ast_channel *chan);
 void ast_channel_timingfunc_set(struct ast_channel *chan, ast_timing_func_t value);
 
 struct ast_bridge *ast_channel_internal_bridge(const struct ast_channel *chan);
+/*!
+ * \pre chan is locked
+ */
 void ast_channel_internal_bridge_set(struct ast_channel *chan, struct ast_bridge *value);
 
 struct ast_bridge_channel *ast_channel_internal_bridge_channel(const struct ast_channel *chan);
index f5f7392..08f9082 100644 (file)
@@ -47,7 +47,10 @@ enum ast_channel_state {
        AST_STATE_MUTE = (1 << 16),     /*!< Do not transmit voice data */
 };
 
-/*! \brief Change the state of a channel */
+/*!
+ * \brief Change the state of a channel
+ * \pre chan is locked
+ */
 int ast_setstate(struct ast_channel *chan, enum ast_channel_state);
 
 #endif /* __AST_CHANNELSTATE_H__ */
index 2d15a33..72bf599 100644 (file)
@@ -203,6 +203,9 @@ struct stasis_message_type *ast_channel_left_bridge_type(void);
  * should also be treated as immutable and not modified after it is put into the
  * message.
  *
+ * \pre bridge is locked.
+ * \pre No channels are locked.
+ *
  * \param bridge Channel blob is associated with, or NULL for global/all bridges.
  * \param blob JSON object representing the data.
  * \return \ref ast_bridge_blob message.
@@ -217,6 +220,9 @@ struct stasis_message *ast_bridge_blob_create(struct stasis_message_type *type,
  * \since 12
  * \brief Publish a bridge channel enter event
  *
+ * \pre bridge is locked.
+ * \pre No channels are locked.
+ *
  * \param bridge The bridge a channel entered
  * \param chan The channel that entered the bridge
  * \param swap The channel being swapped out of the bridge
@@ -228,6 +234,9 @@ void ast_bridge_publish_enter(struct ast_bridge *bridge, struct ast_channel *cha
  * \since 12
  * \brief Publish a bridge channel leave event
  *
+ * \pre bridge is locked.
+ * \pre No channels are locked.
+ *
  * \param bridge The bridge a channel left
  * \param chan The channel that left the bridge
  */
@@ -272,6 +281,8 @@ struct stasis_message_type *ast_blind_transfer_type(void);
 /*!
  * \brief Publish a blind transfer event
  *
+ * \pre No channels or bridges are locked
+ *
  * \param is_external Whether the blind transfer was initiated externally (e.g. via AMI or native protocol)
  * \param result The success or failure of the transfer
  * \param to_transferee The bridge between the transferer and transferee plus the transferer channel
@@ -335,6 +346,8 @@ struct stasis_message_type *ast_attended_transfer_type(void);
  * Publish an \ref ast_attended_transfer_message with the dest_type set to
  * \c AST_ATTENDED_TRANSFER_DEST_FAIL.
  *
+ * \pre No channels or bridges are locked
+ *
  * \param is_external Indicates if the transfer was initiated externally
  * \param result The result of the transfer. Will always be a type of failure.
  * \param transferee The bridge between the transferer and transferees as well as the transferer channel from that bridge
@@ -356,6 +369,8 @@ void ast_bridge_publish_attended_transfer_fail(int is_external, enum ast_transfe
  *
  * In either case, two bridges enter, one leaves.
  *
+ * \pre No channels or bridges are locked
+ *
  * \param is_external Indicates if the transfer was initiated externally
  * \param result The result of the transfer.
  * \param transferee The bridge between the transferer and transferees as well as the transferer channel from that bridge
@@ -375,6 +390,8 @@ void ast_bridge_publish_attended_transfer_bridge_merge(int is_external, enum ast
  * this results from merging two bridges together. The difference is that a
  * transferer channel survives the bridge merge
  *
+ * \pre No channels or bridges are locked
+ *
  * \param is_external Indicates if the transfer was initiated externally
  * \param result The result of the transfer.
  * \param transferee The bridge between the transferer and transferees as well as the transferer channel from that bridge
@@ -396,6 +413,8 @@ void ast_bridge_publish_attended_transfer_threeway(int is_external, enum ast_tra
  * \li A transferee channel leaving a bridge to run an app
  * \li A bridge of transferees running an app (via a local channel)
  *
+ * \pre No channels or bridges are locked
+ *
  * \param is_external Indicates if the transfer was initiated externally
  * \param result The result of the transfer.
  * \param transferee The bridge between the transferer and transferees as well as the transferer channel from that bridge
@@ -419,6 +438,8 @@ void ast_bridge_publish_attended_transfer_app(int is_external, enum ast_transfer
  * When this type of transfer occurs, the two bridges continue to exist after the
  * transfer and a local channel is used to link the two bridges together.
  *
+ * \pre No channels or bridges are locked
+ *
  * \param is_external Indicates if the transfer was initiated externally
  * \param result The result of the transfer.
  * \param transferee The bridge between the transferer and transferees as well as the transferer channel from that bridge
index 8c27803..9c64c1c 100644 (file)
@@ -153,6 +153,8 @@ struct stasis_message_type *ast_channel_snapshot_type(void);
  * \brief Generate a snapshot of the channel state. This is an ao2 object, so
  * ao2_cleanup() to deallocate.
  *
+ * \pre chan is locked
+ *
  * \param chan The channel from which to generate a snapshot
  *
  * \retval pointer on success (must be unreffed)
@@ -192,6 +194,8 @@ struct ast_channel_snapshot *ast_channel_snapshot_get_latest_by_name(const char
  * The given \a blob should be treated as immutable and not modified after it is
  * put into the message.
  *
+ * \pre chan is locked
+ *
  * \param chan Channel blob is associated with, or \c NULL for global/all channels.
  * \param type Message type for this blob.
  * \param blob JSON object representing the data, or \c NULL for no data. If
@@ -305,6 +309,8 @@ void ast_multi_channel_blob_add_channel(struct ast_multi_channel_blob *obj,
  * \brief Publish a channel blob message.
  * \since 12.0.0
  *
+ * \pre chan is locked
+ *
  * \param chan Channel publishing the blob.
  * \param type Type of stasis message.
  * \param blob The blob being published. (NULL if no blob)
@@ -318,6 +324,8 @@ void ast_channel_publish_blob(struct ast_channel *chan, struct stasis_message_ty
  * \since 12
  * \brief Set flag to indicate channel snapshot is being staged.
  *
+ * \pre chan is locked
+ *
  * \param chan Channel being staged.
  */
 void ast_channel_stage_snapshot(struct ast_channel *chan);
@@ -326,6 +334,8 @@ void ast_channel_stage_snapshot(struct ast_channel *chan);
  * \since 12
  * \brief Clear flag to indicate channel snapshot is being staged, and publish snapshot.
  *
+ * \pre chan is locked
+ *
  * \param chan Channel being staged.
  */
 void ast_channel_stage_snapshot_done(struct ast_channel *chan);
@@ -334,6 +344,8 @@ void ast_channel_stage_snapshot_done(struct ast_channel *chan);
  * \since 12
  * \brief Publish a \ref ast_channel_snapshot for a channel.
  *
+ * \pre chan is locked
+ *
  * \param chan Channel to publish.
  */
 void ast_channel_publish_snapshot(struct ast_channel *chan);
@@ -342,6 +354,8 @@ void ast_channel_publish_snapshot(struct ast_channel *chan);
  * \since 12
  * \brief Publish a \ref ast_channel_varset for a channel.
  *
+ * \pre chan is locked
+ *
  * \param chan Channel to publish the event for, or \c NULL for 'none'.
  * \param variable Name of the variable being set
  * \param value Value.
@@ -535,6 +549,8 @@ void ast_channel_publish_dial_forward(struct ast_channel *caller,
  * \brief Publish in the \ref ast_channel_topic a \ref ast_channel_snapshot
  * message indicating a change in channel state
  *
+ * \pre chan is locked
+ *
  * \param chan The channel whose state has changed
  */
 void ast_publish_channel_state(struct ast_channel *chan);
index 8fd7847..8acf260 100644 (file)
@@ -2524,7 +2524,13 @@ static int try_swap_optimize_out(struct ast_bridge *chan_bridge,
 
        other = ast_bridge_channel_peer(src_bridge_channel);
        if (other && other->state == BRIDGE_CHANNEL_STATE_WAIT) {
-               unsigned int id = ast_atomic_fetchadd_int((int *) &optimization_id, +1);
+               unsigned int id;
+
+               if (ast_channel_trylock(other->chan)) {
+                       return 1;
+               }
+
+               id = ast_atomic_fetchadd_int((int *) &optimization_id, +1);
 
                ast_verb(3, "Move-swap optimizing %s <-- %s.\n",
                        ast_channel_name(dst_bridge_channel->chan),
@@ -2546,6 +2552,7 @@ static int try_swap_optimize_out(struct ast_bridge *chan_bridge,
                if (pvt && pvt->callbacks && pvt->callbacks->optimization_finished) {
                        pvt->callbacks->optimization_finished(pvt, res == 1, id);
                }
+               ast_channel_unlock(other->chan);
        }
        return res;
 }
index 96bfb20..ae33cd0 100644 (file)
@@ -235,12 +235,16 @@ void ast_bridge_channel_update_linkedids(struct ast_bridge_channel *bridge_chann
                return;
        }
 
+       ast_channel_lock(bridge_channel->chan);
        ast_channel_linkedid_set(bridge_channel->chan, oldest_linkedid);
+       ast_channel_unlock(bridge_channel->chan);
        AST_LIST_TRAVERSE(&bridge->channels, other, entry) {
                if (other == swap) {
                        continue;
                }
+               ast_channel_lock(other->chan);
                ast_channel_linkedid_set(other->chan, oldest_linkedid);
+               ast_channel_unlock(other->chan);
        }
 }
 
@@ -253,6 +257,7 @@ void ast_bridge_channel_update_accountcodes(struct ast_bridge_channel *bridge_ch
                if (other == swap) {
                        continue;
                }
+               ast_channel_lock_both(bridge_channel->chan, other->chan);
 
                if (!ast_strlen_zero(ast_channel_accountcode(bridge_channel->chan)) && ast_strlen_zero(ast_channel_peeraccount(other->chan))) {
                        ast_debug(1, "Setting peeraccount to %s for %s from data on channel %s\n",
@@ -286,6 +291,8 @@ void ast_bridge_channel_update_accountcodes(struct ast_bridge_channel *bridge_ch
                                ast_channel_peeraccount_set(bridge_channel->chan, ast_channel_accountcode(other->chan));
                        }
                }
+               ast_channel_unlock(bridge_channel->chan);
+               ast_channel_unlock(other->chan);
        }
 }
 
@@ -624,14 +631,18 @@ int ast_bridge_channel_write_hold(struct ast_bridge_channel *bridge_channel, con
                datalen = 0;
        }
 
+       ast_channel_lock(bridge_channel->chan);
        ast_channel_publish_blob(bridge_channel->chan, ast_channel_hold_type(), blob);
+       ast_channel_unlock(bridge_channel->chan);
        return ast_bridge_channel_write_control_data(bridge_channel, AST_CONTROL_HOLD,
                moh_class, datalen);
 }
 
 int ast_bridge_channel_write_unhold(struct ast_bridge_channel *bridge_channel)
 {
+       ast_channel_lock(bridge_channel->chan);
        ast_channel_publish_blob(bridge_channel->chan, ast_channel_unhold_type(), NULL);
+       ast_channel_unlock(bridge_channel->chan);
        return ast_bridge_channel_write_control_data(bridge_channel, AST_CONTROL_UNHOLD, NULL, 0);
 }
 
index db51361..b9f992f 100644 (file)
@@ -1614,7 +1614,9 @@ void ast_cel_publish_event(struct ast_channel *chan,
                "event_type", event_type,
                "event_details", blob);
 
+       ast_channel_lock(chan);
        message = ast_channel_blob_create(chan, cel_generic_type(), cel_blob);
+       ast_channel_unlock(chan);
        if (message) {
                stasis_publish(ast_cel_topic(), message);
        }
index 418e6a7..669b815 100644 (file)
@@ -678,7 +678,9 @@ int ast_str2cause(const char *name)
 static struct stasis_message *create_channel_snapshot_message(struct ast_channel *channel)
 {
        RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
+       ast_channel_lock(channel);
        snapshot = ast_channel_snapshot_create(channel);
+       ast_channel_unlock(channel);
        if (!snapshot) {
                return NULL;
        }
@@ -1267,6 +1269,7 @@ int ast_queue_hold(struct ast_channel *chan, const char *musicclass)
        struct ast_frame f = { AST_FRAME_CONTROL, .subclass.integer = AST_CONTROL_HOLD };
        int res;
 
+       ast_channel_lock(chan);
        if (!ast_strlen_zero(musicclass)) {
                f.data.ptr = (void *) musicclass;
                f.datalen = strlen(musicclass) + 1;
@@ -1278,6 +1281,7 @@ int ast_queue_hold(struct ast_channel *chan, const char *musicclass)
        ast_channel_publish_blob(chan, ast_channel_hold_type(), blob);
 
        res = ast_queue_frame(chan, &f);
+       ast_channel_unlock(chan);
        return res;
 }
 
@@ -1286,9 +1290,11 @@ int ast_queue_unhold(struct ast_channel *chan)
        struct ast_frame f = { AST_FRAME_CONTROL, .subclass.integer = AST_CONTROL_UNHOLD };
        int res;
 
+       ast_channel_lock(chan);
        ast_channel_publish_blob(chan, ast_channel_unhold_type(), NULL);
 
        res = ast_queue_frame(chan, &f);
+       ast_channel_unlock(chan);
        return res;
 }
 
@@ -2254,7 +2260,9 @@ static void ast_channel_destructor(void *obj)
 
        /* Things that may possibly raise Stasis messages shouldn't occur after this point */
        ast_set_flag(ast_channel_flags(chan), AST_FLAG_DEAD);
+       ast_channel_lock(chan);
        ast_channel_publish_snapshot(chan);
+       ast_channel_unlock(chan);
        publish_cache_clear(chan);
 
        ast_channel_lock(chan);
@@ -5324,7 +5332,9 @@ static int set_format(struct ast_channel *chan,
                        generator_write_format_change(chan);
                }
 
+               ast_channel_lock(chan);
                ast_channel_publish_snapshot(chan);
+               ast_channel_unlock(chan);
 
                return 0;
        }
@@ -5405,7 +5415,9 @@ static int set_format(struct ast_channel *chan,
                generator_write_format_change(chan);
        }
 
+       ast_channel_lock(chan);
        ast_channel_publish_snapshot(chan);
+       ast_channel_unlock(chan);
 
        return res;
 }
@@ -5622,7 +5634,9 @@ struct ast_channel *ast_call_forward(struct ast_channel *caller, struct ast_chan
        /* Copy/inherit important information into new channel */
        if (oh) {
                if (oh->vars) {
+                       ast_channel_lock(new_chan);
                        ast_set_variables(new_chan, oh->vars);
+                       ast_channel_unlock(new_chan);
                }
                if (oh->parent_channel) {
                        call_forward_inherit(new_chan, oh->parent_channel, orig);
@@ -5683,7 +5697,9 @@ struct ast_channel *__ast_request_and_dial(const char *type, struct ast_format_c
 
        if (oh) {
                if (oh->vars) {
+                       ast_channel_lock(chan);
                        ast_set_variables(chan, oh->vars);
+                       ast_channel_unlock(chan);
                }
                if (!ast_strlen_zero(oh->cid_num) && !ast_strlen_zero(oh->cid_name)) {
                        /*
@@ -5955,7 +5971,9 @@ struct ast_channel *ast_request(const char *type, struct ast_format_cap *request
                if (requestor) {
                        struct ast_callid *callid = ast_channel_callid(requestor);
                        if (callid) {
+                               ast_channel_lock(c);
                                ast_channel_callid_set(c, callid);
+                               ast_channel_unlock(c);
                                callid = ast_callid_unref(callid);
                        }
                }
index 4a04703..edf2839 100644 (file)
@@ -498,29 +498,32 @@ static void publish_local_bridge_message(struct local_pvt *p)
        RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
        RAII_VAR(struct ast_channel_snapshot *, one_snapshot, NULL, ao2_cleanup);
        RAII_VAR(struct ast_channel_snapshot *, two_snapshot, NULL, ao2_cleanup);
-       SCOPED_AO2LOCK(lock, p);
+       struct ast_channel *owner;
+       struct ast_channel *chan;
+
+       ast_unreal_lock_all(&p->base, &chan, &owner);
 
        blob = ast_json_pack("{s: s, s: s, s: b}",
                "context", p->context,
                "exten", p->exten,
                "can_optimize", !ast_test_flag(&p->base, AST_UNREAL_NO_OPTIMIZATION));
        if (!blob) {
-               return;
+               goto end;
        }
 
        multi_blob = ast_multi_channel_blob_create(blob);
        if (!multi_blob) {
-               return;
+               goto end;
        }
 
-       one_snapshot = ast_channel_snapshot_create(p->base.owner);
+       one_snapshot = ast_channel_snapshot_create(owner);
        if (!one_snapshot) {
-               return;
+               goto end;
        }
 
-       two_snapshot = ast_channel_snapshot_create(p->base.chan);
+       two_snapshot = ast_channel_snapshot_create(chan);
        if (!two_snapshot) {
-               return;
+               goto end;
        }
 
        ast_multi_channel_blob_add_channel(multi_blob, "1", one_snapshot);
@@ -528,10 +531,19 @@ static void publish_local_bridge_message(struct local_pvt *p)
 
        msg = stasis_message_create(ast_local_bridge_type(), multi_blob);
        if (!msg) {
-               return;
+               goto end;
        }
 
-       stasis_publish(ast_channel_topic(p->base.owner), msg);
+       stasis_publish(ast_channel_topic(owner), msg);
+
+end:
+       ast_channel_unlock(owner);
+       ast_channel_unref(owner);
+
+       ast_channel_unlock(chan);
+       ast_channel_unref(chan);
+
+       ao2_unlock(&p->base);
 }
 
 int ast_local_setup_bridge(struct ast_channel *ast, struct ast_bridge *bridge, struct ast_channel *swap, struct ast_bridge_features *features)
index ca0b9c8..6ff0e7f 100644 (file)
@@ -303,6 +303,7 @@ static int begin_dial_prerun(struct ast_dial_channel *channel, struct ast_channe
        cap_request = NULL;
        cap_all_audio = ast_format_cap_destroy(cap_all_audio);
 
+       ast_channel_lock(channel->owner);
        ast_channel_stage_snapshot(channel->owner);
 
        ast_channel_appl_set(channel->owner, "AppDial2");
@@ -332,6 +333,7 @@ static int begin_dial_prerun(struct ast_dial_channel *channel, struct ast_channe
        }
 
        ast_channel_stage_snapshot_done(channel->owner);
+       ast_channel_unlock(channel->owner);
 
        if (!ast_strlen_zero(predial_string)) {
                const char *predial_callee = ast_app_expand_sub_args(chan, predial_string);
index 4be4eb3..9cc0178 100644 (file)
@@ -203,7 +203,9 @@ int ast_endpoint_add_channel(struct ast_endpoint *endpoint,
        ast_str_container_add(endpoint->channel_ids, ast_channel_uniqueid(chan));
        ao2_unlock(endpoint);
 
+       ast_channel_lock(chan);
        ast_publish_channel_state(chan);
+       ast_channel_unlock(chan);
        endpoint_publish_snapshot(endpoint);
 
        return 0;
index 726677f..1e6a246 100644 (file)
@@ -1612,9 +1612,11 @@ int pbx_exec(struct ast_channel *c,      /*!< Channel */
        saved_c_appl= ast_channel_appl(c);
        saved_c_data= ast_channel_data(c);
 
+       ast_channel_lock(c);
        ast_channel_appl_set(c, app->name);
        ast_channel_data_set(c, data);
        ast_channel_publish_snapshot(c);
+       ast_channel_unlock(c);
 
        if (app->module)
                u = __ast_module_user_add(app->module, c);
@@ -6281,7 +6283,9 @@ static enum ast_pbx_result __ast_pbx_run(struct ast_channel *c,
                if (!callid) {
                        callid = ast_create_callid();
                        if (callid) {
+                               ast_channel_lock(c);
                                ast_channel_callid_set(c, callid);
+                               ast_channel_unlock(c);
                        }
                }
                ast_callid_threadassoc_add(callid);
@@ -10249,6 +10253,7 @@ static int pbx_outgoing_attempt(const char *type, struct ast_format_cap *cap, co
                return -1;
        }
 
+       ast_channel_lock(dialed);
        if (vars) {
                ast_set_variables(dialed, vars);
        }
@@ -10257,6 +10262,7 @@ static int pbx_outgoing_attempt(const char *type, struct ast_format_cap *cap, co
                ast_channel_accountcode_set(dialed, account);
        }
        ast_set_flag(ast_channel_flags(dialed), AST_FLAG_ORIGINATED);
+       ast_channel_unlock(dialed);
 
        if (!ast_strlen_zero(cid_num) || !ast_strlen_zero(cid_name)) {
                struct ast_party_connected_line connected;
@@ -10364,7 +10370,6 @@ static int pbx_outgoing_attempt(const char *type, struct ast_format_cap *cap, co
                        ast_set_variables(failed, vars);
                        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)) {
@@ -10666,10 +10671,12 @@ static int pbx_builtin_busy(struct ast_channel *chan, const char *data)
        ast_indicate(chan, AST_CONTROL_BUSY);
        /* Don't change state of an UP channel, just indicate
           busy in audio */
+       ast_channel_lock(chan);
        if (ast_channel_state(chan) != AST_STATE_UP) {
                ast_channel_hangupcause_set(chan, AST_CAUSE_BUSY);
                ast_setstate(chan, AST_STATE_BUSY);
        }
+       ast_channel_unlock(chan);
        wait_for_hangup(chan, data);
        return -1;
 }
@@ -10682,10 +10689,12 @@ static int pbx_builtin_congestion(struct ast_channel *chan, const char *data)
        ast_indicate(chan, AST_CONTROL_CONGESTION);
        /* Don't change state of an UP channel, just indicate
           congestion in audio */
+       ast_channel_lock(chan);
        if (ast_channel_state(chan) != AST_STATE_UP) {
                ast_channel_hangupcause_set(chan, AST_CAUSE_CONGESTION);
                ast_setstate(chan, AST_STATE_BUSY);
        }
+       ast_channel_unlock(chan);
        wait_for_hangup(chan, data);
        return -1;
 }
index 7ae6927..a415f16 100644 (file)
@@ -354,11 +354,17 @@ int ast_do_pickup(struct ast_channel *chan, struct ast_channel *target)
        /* setting the HANGUPCAUSE so the ringing channel knows this call was not a missed call */
        ast_channel_hangupcause_set(chan, AST_CAUSE_ANSWERED_ELSEWHERE);
 
-       if (!(chan_snapshot = ast_channel_snapshot_create(chan))) {
+       ast_channel_lock(chan);
+       chan_snapshot = ast_channel_snapshot_create(chan);
+       ast_channel_unlock(chan);
+       if (!chan_snapshot) {
                goto pickup_failed;
        }
 
-       if (!(target_snapshot = ast_channel_snapshot_create(target))) {
+       ast_channel_lock(target);
+       target_snapshot = ast_channel_snapshot_create(target);
+       ast_channel_unlock(target);
+       if (!target_snapshot) {
                goto pickup_failed;
        }
 
index 7f6679b..b8d4ae8 100644 (file)
@@ -399,7 +399,9 @@ struct stasis_message *ast_bridge_blob_create(
        }
 
        if (chan) {
+               ast_channel_lock(chan);
                obj->channel = ast_channel_snapshot_create(chan);
+               ast_channel_unlock(chan);
                if (obj->channel == NULL) {
                        return NULL;
                }
@@ -583,7 +585,9 @@ static int bridge_channel_snapshot_pair_init(struct ast_bridge_channel_pair *pai
                }
        }
 
+       ast_channel_lock(pair->channel);
        snapshot_pair->channel_snapshot = ast_channel_snapshot_create(pair->channel);
+       ast_channel_unlock(pair->channel);
        if (!snapshot_pair->channel_snapshot) {
                return -1;
        }
@@ -919,7 +923,9 @@ void ast_bridge_publish_attended_transfer_link(int is_external, enum ast_transfe
 
        transfer_msg->dest_type = AST_ATTENDED_TRANSFER_DEST_LINK;
        for (i = 0; i < 2; ++i) {
+               ast_channel_lock(locals[i]);
                transfer_msg->dest.links[i] = ast_channel_snapshot_create(locals[i]);
+               ast_channel_unlock(locals[i]);
                if (!transfer_msg->dest.links[i]) {
                        return;
                }
index 8a39bdf..677527b 100644 (file)
@@ -317,14 +317,18 @@ void ast_channel_publish_dial_forward(struct ast_channel *caller, struct ast_cha
        }
 
        if (caller) {
+               ast_channel_lock(caller);
                caller_snapshot = ast_channel_snapshot_create(caller);
+               ast_channel_unlock(caller);
                if (!caller_snapshot) {
                        return;
                }
                ast_multi_channel_blob_add_channel(payload, "caller", caller_snapshot);
        }
 
+       ast_channel_lock(peer);
        peer_snapshot = ast_channel_snapshot_create(peer);
+       ast_channel_unlock(peer);
        if (!peer_snapshot) {
                return;
        }
index f9f9cb2..7624d59 100644 (file)
@@ -357,7 +357,9 @@ static int realtime_exec(struct ast_channel *chan, const char *context, const ch
                                                 term_color(tmp1, app, COLOR_BRCYAN, 0, sizeof(tmp1)),
                                                 term_color(tmp2, ast_channel_name(chan), COLOR_BRMAGENTA, 0, sizeof(tmp2)),
                                                 term_color(tmp3, S_OR(appdata, ""), COLOR_BRMAGENTA, 0, sizeof(tmp3)));
+                               ast_channel_lock(chan);
                                snapshot = ast_channel_snapshot_create(chan);
+                               ast_channel_unlock(chan);
                                if (snapshot) {
                                        /* pbx_exec sets application name and data, but we don't want to log
                                         * every exec. Just update the snapshot here instead.
index ba0ffdd..bf211a2 100644 (file)
@@ -530,6 +530,7 @@ static int parking_duration_callback(struct ast_bridge_channel *bridge_channel,
 
        /* Set parking timeout channel variables */
        snprintf(parking_space, sizeof(parking_space), "%d", user->parking_space);
+       ast_channel_lock(chan);
        ast_channel_stage_snapshot(chan);
        pbx_builtin_setvar_helper(chan, "PARKING_SPACE", parking_space);
        pbx_builtin_setvar_helper(chan, "PARKINGSLOT", parking_space); /* Deprecated version of PARKING_SPACE */
@@ -538,6 +539,7 @@ static int parking_duration_callback(struct ast_bridge_channel *bridge_channel,
        pbx_builtin_setvar_helper(chan, "PARKER_FLAT", dial_string_flat);
        parking_timeout_set_caller_features(chan, user->lot->cfg);
        ast_channel_stage_snapshot_done(chan);
+       ast_channel_unlock(chan);
 
        /* Dialplan generation for park-dial extensions */
 
index 60baa65..9d8c236 100644 (file)
@@ -155,7 +155,9 @@ static struct ast_parked_call_payload *parked_call_payload_from_failure(struct a
        RAII_VAR(struct ast_parked_call_payload *, payload, NULL, ao2_cleanup);
        RAII_VAR(struct ast_channel_snapshot *, parkee_snapshot, NULL, ao2_cleanup);
 
+       ast_channel_lock(chan);
        parkee_snapshot = ast_channel_snapshot_create(chan);
+       ast_channel_unlock(chan);
        if (!parkee_snapshot) {
                return NULL;
        }
@@ -172,7 +174,9 @@ static struct ast_parked_call_payload *parked_call_payload_from_parked_user(stru
        struct timeval now = ast_tvnow();
        const char *lot_name = pu->lot->name;
 
+       ast_channel_lock(pu->chan);
        parkee_snapshot = ast_channel_snapshot_create(pu->chan);
+       ast_channel_unlock(pu->chan);
 
        if (!parkee_snapshot) {
                return NULL;
index ed70356..96d3906 100644 (file)
@@ -1481,9 +1481,11 @@ static enum agi_result launch_asyncagi(struct ast_channel *chan, int argc, char
           to execute based on the setup info */
        ast_uri_encode(agi_buffer, ami_buffer, AMI_BUF_SIZE, ast_uri_http);
        startblob = ast_json_pack("{s: s}", "Env", ami_buffer);
+       ast_channel_lock(chan);
        ast_channel_publish_blob(chan, agi_async_start_type(), startblob);
 
        hungup = ast_check_hangup(chan);
+       ast_channel_unlock(chan);
        for (;;) {
                /*
                 * Process as many commands as we can.  Commands are added via
@@ -1527,7 +1529,9 @@ static enum agi_result launch_asyncagi(struct ast_channel *chan, int argc, char
                        if (execblob && !ast_strlen_zero(cmd->cmd_id)) {
                                ast_json_object_set(execblob, "CommandId", ast_json_string_create(cmd->cmd_id));
                        }
+                       ast_channel_lock(chan);
                        ast_channel_publish_blob(chan, agi_async_exec_type(), execblob);
+                       ast_channel_unlock(chan);
 
                        free_agi_cmd(cmd);
 
@@ -1587,7 +1591,9 @@ async_agi_done:
                ast_speech_destroy(async_agi.speech);
        }
        /* notify manager users this channel cannot be controlled anymore by Async AGI */
+       ast_channel_lock(chan);
        ast_channel_publish_blob(chan, agi_async_end_type(), NULL);
+       ast_channel_unlock(chan);
 
 async_agi_abort:
        /* close the pipe */
@@ -2716,7 +2722,9 @@ static int handle_autohangup(struct ast_channel *chan, AGI *agi, int argc, const
                whentohangup.tv_sec = timeout;
                whentohangup.tv_usec = (timeout - whentohangup.tv_sec) * 1000000.0;
        }
+       ast_channel_lock(chan);
        ast_channel_setwhentohangup_tv(chan, whentohangup);
+       ast_channel_unlock(chan);
        ast_agi_send(agi->fd, chan, "200 result=0\n");
        return RESULT_SUCCESS;
 }
@@ -3657,7 +3665,9 @@ static void publish_async_exec_end(struct ast_channel *chan, int command_id, con
                             "Command", command,
                             "ResultCode", result_code,
                             "Result", result);
+       ast_channel_lock(chan);
        ast_channel_publish_blob(chan, agi_exec_end_type(), blob);
+       ast_channel_unlock(chan);
 }
 
 static enum agi_result agi_handle_command(struct ast_channel *chan, AGI *agi, char *buf, int dead)
@@ -3675,7 +3685,9 @@ static enum agi_result agi_handle_command(struct ast_channel *chan, AGI *agi, ch
        startblob = ast_json_pack("{s: i, s: s}",
                             "CommandId", command_id,
                             "Command", ami_cmd);
+       ast_channel_lock(chan);
        ast_channel_publish_blob(chan, agi_exec_start_type(), startblob);
+       ast_channel_unlock(chan);
 
        parse_args(buf, &argc, argv);
        c = find_command(argv, 0);
index 91da22f..da48e52 100644 (file)
@@ -754,7 +754,9 @@ static int refer_incoming_invite_request(struct ast_sip_session *session, struct
                goto end;
        }
 
+       ast_channel_lock(session->channel);
        ast_setstate(session->channel, AST_STATE_RING);
+       ast_channel_unlock(session->channel);
        ast_raw_answer(session->channel);
 
        if (!invite.bridge) {
index 71a18a0..32de9a0 100644 (file)
@@ -637,7 +637,9 @@ static int send_start_msg(struct stasis_app *app, struct ast_channel *chan,
        ast_assert(chan != NULL);
 
        /* Set channel info */
+       ast_channel_lock(chan);
        snapshot = ast_channel_snapshot_create(chan);
+       ast_channel_unlock(chan);
        if (!snapshot) {
                return -1;
        }
@@ -681,7 +683,9 @@ static int send_end_msg(struct stasis_app *app, struct ast_channel *chan)
        ast_assert(chan != NULL);
 
        /* Set channel info */
+       ast_channel_lock(chan);
        snapshot = ast_channel_snapshot_create(chan);
+       ast_channel_unlock(chan);
        if (snapshot == NULL) {
                return -1;
        }
index e70a064..946b570 100644 (file)
@@ -276,9 +276,11 @@ static void clear_mock_cdr_backend(void)
        if ((priority) > 0) { \
                ast_channel_priority_set((channel), (priority)); \
        } \
+       ast_channel_lock((channel)); \
        ast_channel_appl_set((channel), (application)); \
        ast_channel_data_set((channel), (data)); \
        ast_channel_publish_snapshot((channel)); \
+       ast_channel_unlock((channel)); \
        } while (0)
 
 /*! \brief Hang up a test channel safely */
@@ -635,9 +637,11 @@ AST_TEST_DEFINE(test_cdr_single_party)
        SWAP_CONFIG(config, debug_cdr_config);
        CREATE_ALICE_CHANNEL(chan, &caller, &expected);
 
+       ast_channel_lock(chan);
        EMULATE_APP_DATA(chan, 1, "Answer", "");
        ast_setstate(chan, AST_STATE_UP);
        EMULATE_APP_DATA(chan, 2, "VoiceMailMain", "1");
+       ast_channel_unlock(chan);
 
        HANGUP_CHANNEL(chan, AST_CAUSE_NORMAL);
 
@@ -684,9 +688,11 @@ AST_TEST_DEFINE(test_cdr_single_bridge)
        SWAP_CONFIG(config, debug_cdr_config);
        CREATE_ALICE_CHANNEL(chan, &caller, &expected);
 
+       ast_channel_lock(chan);
        EMULATE_APP_DATA(chan, 1, "Answer", "");
        ast_setstate(chan, AST_STATE_UP);
        EMULATE_APP_DATA(chan, 2, "Bridge", "");
+       ast_channel_unlock(chan);
 
        bridge = ast_bridge_basic_new();
        ast_test_validate(test, bridge != NULL);
@@ -759,9 +765,11 @@ AST_TEST_DEFINE(test_cdr_single_bridge_continue)
        CREATE_ALICE_CHANNEL(chan, &caller, &expected_one);
        COPY_IDS(chan, &expected_two);
 
+       ast_channel_lock(chan);
        EMULATE_APP_DATA(chan, 1, "Answer", "");
        ast_setstate(chan, AST_STATE_UP);
        EMULATE_APP_DATA(chan, 2, "Bridge", "");
+       ast_channel_unlock(chan);
 
        bridge_one = ast_bridge_basic_new();
        ast_test_validate(test, bridge_one != NULL);
@@ -843,9 +851,11 @@ AST_TEST_DEFINE(test_cdr_single_twoparty_bridge_a)
        CREATE_BOB_CHANNEL(chan_bob, &caller_bob, &bob_expected);
        ast_copy_string(bob_expected.linkedid, ast_channel_linkedid(chan_alice), sizeof(bob_expected.linkedid));
 
+       ast_channel_lock(chan_alice);
        EMULATE_APP_DATA(chan_alice, 1, "Answer", "");
        ast_setstate(chan_alice, AST_STATE_UP);
        EMULATE_APP_DATA(chan_alice, 2, "Bridge", "");
+       ast_channel_unlock(chan_alice);
 
        bridge = ast_bridge_basic_new();
        ast_test_validate(test, bridge != NULL);
@@ -853,9 +863,11 @@ AST_TEST_DEFINE(test_cdr_single_twoparty_bridge_a)
        ast_test_validate(test, !ast_bridge_impart(bridge, chan_alice, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE));
        while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
 
+       ast_channel_lock(chan_bob);
        EMULATE_APP_DATA(chan_bob, 1, "Answer", "");
        ast_setstate(chan_bob, AST_STATE_UP);
        EMULATE_APP_DATA(chan_bob, 2, "Bridge", "");
+       ast_channel_unlock(chan_bob);
 
        ast_test_validate(test, !ast_bridge_impart(bridge, chan_bob, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE));
        while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
@@ -931,16 +943,20 @@ AST_TEST_DEFINE(test_cdr_single_twoparty_bridge_b)
        CREATE_BOB_CHANNEL(chan_bob, &caller_bob, &bob_expected);
        ast_copy_string(bob_expected.linkedid, ast_channel_linkedid(chan_alice), sizeof(bob_expected.linkedid));
 
+       ast_channel_unlock(chan_alice);
        EMULATE_APP_DATA(chan_alice, 1, "Answer", "");
        ast_setstate(chan_alice, AST_STATE_UP);
        EMULATE_APP_DATA(chan_alice, 2, "Bridge", "");
+       ast_channel_unlock(chan_alice);
 
        bridge = ast_bridge_basic_new();
        ast_test_validate(test, bridge != NULL);
 
+       ast_channel_lock(chan_bob);
        EMULATE_APP_DATA(chan_bob, 1, "Answer", "");
        ast_setstate(chan_bob, AST_STATE_UP);
        EMULATE_APP_DATA(chan_bob, 2, "Bridge", "");
+       ast_channel_unlock(chan_bob);
        while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
 
        ast_test_validate(test, !ast_bridge_impart(bridge, chan_bob, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE));
@@ -1054,9 +1070,11 @@ AST_TEST_DEFINE(test_cdr_single_multiparty_bridge)
        CREATE_CHARLIE_CHANNEL(chan_charlie, &caller_charlie, &charlie_expected);
        ast_copy_string(charlie_expected.linkedid, ast_channel_linkedid(chan_alice), sizeof(charlie_expected.linkedid));
 
+       ast_channel_lock(chan_alice);
        EMULATE_APP_DATA(chan_alice, 1, "Answer", "");
        ast_setstate(chan_alice, AST_STATE_UP);
        EMULATE_APP_DATA(chan_alice, 2, "Bridge", "");
+       ast_channel_unlock(chan_alice);
 
        bridge = ast_bridge_basic_new();
        ast_test_validate(test, bridge != NULL);
@@ -1064,18 +1082,22 @@ AST_TEST_DEFINE(test_cdr_single_multiparty_bridge)
 
        ast_test_validate(test, !ast_bridge_impart(bridge, chan_alice, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE));
 
+       ast_channel_lock(chan_bob);
        EMULATE_APP_DATA(chan_bob, 1, "Answer", "");
        ast_setstate(chan_bob, AST_STATE_UP);
        EMULATE_APP_DATA(chan_bob, 2, "Bridge", "");
+       ast_channel_unlock(chan_bob);
        while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
 
        ast_test_validate(test, !ast_bridge_impart(bridge, chan_bob, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE));
 
        while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
 
+       ast_channel_lock(chan_charlie);
        EMULATE_APP_DATA(chan_charlie, 1, "Answer", "");
        ast_setstate(chan_charlie, AST_STATE_UP);
        EMULATE_APP_DATA(chan_charlie, 2, "Bridge", "");
+       ast_channel_unlock(chan_charlie);
        ast_test_validate(test, !ast_bridge_impart(bridge, chan_charlie, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE));
 
        while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
@@ -2018,10 +2040,15 @@ AST_TEST_DEFINE(test_cdr_park)
        CREATE_ALICE_CHANNEL(chan_alice, &alice_caller, &alice_expected);
        CREATE_BOB_CHANNEL(chan_bob, &bob_caller, &bob_expected);
 
+       ast_channel_lock(chan_alice);
        EMULATE_APP_DATA(chan_alice, 1, "Park", "700");
        ast_setstate(chan_alice, AST_STATE_UP);
+       ast_channel_unlock(chan_alice);
+
+       ast_channel_lock(chan_bob);
        EMULATE_APP_DATA(chan_bob, 1, "Park", "701");
        ast_setstate(chan_bob, AST_STATE_UP);
+       ast_channel_unlock(chan_bob);
 
        bridge = ast_bridge_base_new(AST_BRIDGE_CAPABILITY_HOLDING,
                AST_BRIDGE_FLAG_MERGE_INHIBIT_TO | AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM
@@ -2127,6 +2154,7 @@ AST_TEST_DEFINE(test_cdr_fields)
        ast_copy_string(fork_expected_two.linkedid, ast_channel_linkedid(chan), sizeof(fork_expected_two.linkedid));
 
        /* Channel enters Wait app */
+       ast_channel_lock(chan);
        ast_channel_appl_set(chan, "Wait");
        ast_channel_data_set(chan, "10");
        ast_channel_priority_set(chan, 1);
@@ -2135,6 +2163,7 @@ AST_TEST_DEFINE(test_cdr_fields)
        /* Set properties on the channel that propagate to the CDR */
        ast_channel_amaflags_set(chan, AST_AMA_OMIT);
        ast_channel_accountcode_set(chan, "XXX");
+       ast_channel_unlock(chan);
 
        /* Wait one second so we get a duration. */
        while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
@@ -2227,6 +2256,7 @@ AST_TEST_DEFINE(test_cdr_fields)
        ast_test_validate(test, ast_cdr_fork(ast_channel_name(chan), &fork_options) == 0);
 
        /* Channel enters Answer app */
+       ast_channel_lock(chan);
        ast_channel_appl_set(chan, "Answer");
        ast_channel_data_set(chan, "");
        ast_channel_priority_set(chan, 1);
@@ -2235,6 +2265,7 @@ AST_TEST_DEFINE(test_cdr_fields)
 
        /* Set properties on the last record */
        ast_channel_accountcode_set(chan, "ZZZ");
+       ast_channel_unlock(chan);
        ast_cdr_setuserfield(ast_channel_name(chan), "schmackity");
        ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "test_variable", "record_2") == 0);
 
@@ -2404,7 +2435,9 @@ AST_TEST_DEFINE(test_cdr_fork_cdr)
        ast_test_validate(test, ast_cdr_fork(ast_channel_name(chan), &fork_options) == 0);
 
        /* Test keep variables; setting a new answer time */
+       ast_channel_lock(chan);
        ast_setstate(chan, AST_STATE_UP);
+       ast_channel_unlock(chan);
        while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
        ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "test_variable", "record_2") == 0);
        ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "test_variable", varbuffer, sizeof(varbuffer)) == 0);
index 7da4f9e..62a3288 100644 (file)
@@ -1560,10 +1560,14 @@ AST_TEST_DEFINE(test_cel_local_optimize)
        CREATE_ALICE_CHANNEL(chan_alice, &alice_caller);
        CREATE_BOB_CHANNEL(chan_bob, &bob_caller);
 
+       ast_channel_lock(chan_alice);
        alice_snapshot = ast_channel_snapshot_create(chan_alice);
+       ast_channel_unlock(chan_alice);
        ast_test_validate(test, alice_snapshot != NULL);
 
+       ast_channel_lock(chan_bob);
        bob_snapshot = ast_channel_snapshot_create(chan_bob);
+       ast_channel_unlock(chan_bob);
        ast_test_validate(test, bob_snapshot != NULL);
 
        ast_multi_channel_blob_add_channel(mc_blob, "1", alice_snapshot);
@@ -1684,7 +1688,9 @@ static int append_expected_event(
        const char *peer)
 {
        RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
+       ast_channel_lock(chan);
        snapshot = ast_channel_snapshot_create(chan);
+       ast_channel_unlock(chan);
        if (!snapshot) {
                return -1;
        }
index de44545..28961ed 100644 (file)
@@ -78,10 +78,12 @@ AST_TEST_DEFINE(channel_blob_create)
                     "foo", "bar");
 
        /* Off nominal creation */
+       ast_channel_lock(chan);
        ast_test_validate(test, NULL == ast_channel_blob_create(chan, NULL, json));
 
        /* Test for single channel */
        msg = ast_channel_blob_create(chan, type, json);
+       ast_channel_unlock(chan);
        ast_test_validate(test, NULL != msg);
        blob = stasis_message_data(msg);
        ast_test_validate(test, NULL != blob);
@@ -131,7 +133,9 @@ AST_TEST_DEFINE(null_blob)
                     "foo", "bar");
 
        /* Test for single channel */
+       ast_channel_lock(chan);
        msg = ast_channel_blob_create(chan, type, NULL);
+       ast_channel_unlock(chan);
        ast_test_validate(test, NULL != msg);
        blob = stasis_message_data(msg);
        ast_test_validate(test, NULL != blob);
@@ -201,9 +205,15 @@ AST_TEST_DEFINE(multi_channel_blob_snapshots)
        ast_channel_unlock(chan_charlie);
 
        blob = ast_multi_channel_blob_create(json);
+       ast_channel_lock(chan_alice);
        ast_multi_channel_blob_add_channel(blob, "Caller", ast_channel_snapshot_create(chan_alice));
+       ast_channel_unlock(chan_alice);
+       ast_channel_lock(chan_bob);
        ast_multi_channel_blob_add_channel(blob, "Peer", ast_channel_snapshot_create(chan_bob));
+       ast_channel_unlock(chan_bob);
+       ast_channel_lock(chan_charlie);
        ast_multi_channel_blob_add_channel(blob, "Peer", ast_channel_snapshot_create(chan_charlie));
+       ast_channel_unlock(chan_charlie);
 
        /* Test for unknown role */
        ast_test_validate(test, NULL == ast_multi_channel_blob_get_channel(blob, "Foobar"));
@@ -258,7 +268,9 @@ AST_TEST_DEFINE(channel_snapshot_json)
        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);
+       ast_channel_lock(chan);
        snapshot = ast_channel_snapshot_create(chan);
+       ast_channel_unlock(chan);
        ast_test_validate(test, NULL != snapshot);
 
        actual = ast_channel_snapshot_to_json(snapshot, NULL);