summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Michelson <mmichelson@digium.com>2013-12-03 17:07:29 +0000
committerMark Michelson <mmichelson@digium.com>2013-12-03 17:07:29 +0000
commit8e8b329e14ad2e4d747c4c4eb33c118305401aee (patch)
tree200a9b111d9cf75ab980aedf53ee714b7cc398f2
parent8b24b0d20647697c9ee899dea85871465c3032cb (diff)
Add channel locking for channel snapshot creation.
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. ........ Merged revisions 403311 from http://svn.asterisk.org/svn/asterisk/branches/12 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@403314 65c4cc65-6c06-0410-ace0-fbb531ad65f3
-rw-r--r--addons/chan_mobile.c2
-rw-r--r--addons/chan_ooh323.c2
-rw-r--r--apps/app_agent_pool.c4
-rw-r--r--apps/app_confbridge.c2
-rw-r--r--apps/app_dial.c16
-rw-r--r--apps/app_disa.c5
-rw-r--r--apps/app_meetme.c2
-rw-r--r--apps/app_queue.c13
-rw-r--r--apps/app_userevent.c2
-rw-r--r--apps/app_voicemail.c5
-rw-r--r--channels/chan_alsa.c2
-rw-r--r--channels/chan_console.c2
-rw-r--r--channels/chan_dahdi.c8
-rw-r--r--channels/chan_gtalk.c4
-rw-r--r--channels/chan_h323.c4
-rw-r--r--channels/chan_iax2.c7
-rw-r--r--channels/chan_jingle.c4
-rw-r--r--channels/chan_mgcp.c4
-rw-r--r--channels/chan_misdn.c14
-rw-r--r--channels/chan_motif.c4
-rw-r--r--channels/chan_nbs.c2
-rw-r--r--channels/chan_oss.c2
-rw-r--r--channels/chan_phone.c2
-rw-r--r--channels/chan_pjsip.c13
-rw-r--r--channels/chan_sip.c2
-rw-r--r--channels/chan_skinny.c4
-rw-r--r--channels/chan_unistim.c6
-rw-r--r--channels/chan_vpb.cc2
-rw-r--r--channels/sig_analog.c4
-rw-r--r--channels/sig_pri.c2
-rw-r--r--funcs/func_timeout.c2
-rw-r--r--include/asterisk/aoc.h5
-rw-r--r--include/asterisk/channel.h38
-rw-r--r--include/asterisk/channelstate.h5
-rw-r--r--include/asterisk/stasis_bridges.h21
-rw-r--r--include/asterisk/stasis_channels.h16
-rw-r--r--main/bridge.c9
-rw-r--r--main/bridge_channel.c11
-rw-r--r--main/cel.c2
-rw-r--r--main/channel.c18
-rw-r--r--main/core_local.c26
-rw-r--r--main/core_unreal.c4
-rw-r--r--main/dial.c2
-rw-r--r--main/endpoints.c2
-rw-r--r--main/pbx.c12
-rw-r--r--main/pickup.c10
-rw-r--r--main/stasis_bridges.c6
-rw-r--r--main/stasis_channels.c4
-rw-r--r--pbx/pbx_realtime.c2
-rw-r--r--res/parking/parking_bridge_features.c2
-rw-r--r--res/parking/parking_manager.c4
-rw-r--r--res/res_agi.c12
-rw-r--r--res/res_pjsip_refer.c2
-rw-r--r--res/res_stasis.c4
-rw-r--r--tests/test_cdr.c33
-rw-r--r--tests/test_cel.c6
-rw-r--r--tests/test_stasis_channels.c12
57 files changed, 384 insertions, 31 deletions
diff --git a/addons/chan_mobile.c b/addons/chan_mobile.c
index 2cf7c7dbd..c9e56b854 100644
--- a/addons/chan_mobile.c
+++ b/addons/chan_mobile.c
@@ -861,6 +861,7 @@ static struct ast_channel *mbl_new(int state, struct mbl_pvt *pvt, char *cid_num
goto e_return;
}
+ ast_channel_lock(chn);
ast_channel_tech_set(chn, &mbl_tech);
ast_format_cap_add(ast_channel_nativeformats(chn), &prefformat);
ast_format_copy(ast_channel_rawreadformat(chn), &prefformat);
@@ -878,6 +879,7 @@ 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;
diff --git a/addons/chan_ooh323.c b/addons/chan_ooh323.c
index 56a1b7b68..deec21fa7 100644
--- a/addons/chan_ooh323.c
+++ b/addons/chan_ooh323.c
@@ -2153,8 +2153,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);
diff --git a/apps/app_agent_pool.c b/apps/app_agent_pool.c
index c968153e6..d49ec2348 100644
--- a/apps/app_agent_pool.c
+++ b/apps/app_agent_pool.c
@@ -1464,7 +1464,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);
@@ -2045,7 +2047,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;
diff --git a/apps/app_confbridge.c b/apps/app_confbridge.c
index 8347bc6ed..a886b5876 100644
--- a/apps/app_confbridge.c
+++ b/apps/app_confbridge.c
@@ -1368,7 +1368,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);
diff --git a/apps/app_dial.c b/apps/app_dial.c
index c9bee19b0..c52a9b917 100644
--- a/apps/app_dial.c
+++ b/apps/app_dial.c
@@ -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);
diff --git a/apps/app_disa.c b/apps/app_disa.c
index fe53772f1..9e7412717 100644
--- a/apps/app_disa.c
+++ b/apps/app_disa.c
@@ -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);
diff --git a/apps/app_meetme.c b/apps/app_meetme.c
index ffd55e70d..d9bdeb605 100644
--- a/apps/app_meetme.c
+++ b/apps/app_meetme.c
@@ -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;
diff --git a/apps/app_queue.c b/apps/app_queue.c
index 906dff15f..713dba2d7 100644
--- a/apps/app_queue.c
+++ b/apps/app_queue.c
@@ -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. */
diff --git a/apps/app_userevent.c b/apps/app_userevent.c
index e0dafbb9f..f5defd49d 100644
--- a/apps/app_userevent.c
+++ b/apps/app_userevent.c
@@ -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;
}
diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c
index dca4eceee..7abf4530e 100644
--- a/apps/app_voicemail.c
+++ b/apps/app_voicemail.c
@@ -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");
diff --git a/channels/chan_alsa.c b/channels/chan_alsa.c
index 60bbacbb8..065eff551 100644
--- a/channels/chan_alsa.c
+++ b/channels/chan_alsa.c
@@ -581,6 +581,7 @@ static struct ast_channel *alsa_new(struct chan_alsa_pvt *p, int state, const ch
if (!(tmp = ast_channel_alloc(1, state, 0, 0, "", p->exten, p->context, linkedid, 0, "ALSA/%s", indevname)))
return NULL;
+ ast_channel_lock(tmp);
ast_channel_stage_snapshot(tmp);
ast_channel_tech_set(tmp, &alsa_tech);
@@ -601,6 +602,7 @@ 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) {
if (ast_pbx_start(tmp)) {
diff --git a/channels/chan_console.c b/channels/chan_console.c
index 922c53b42..6f694c2c9 100644
--- a/channels/chan_console.c
+++ b/channels/chan_console.c
@@ -428,6 +428,7 @@ static struct ast_channel *console_new(struct console_pvt *pvt, const char *ext,
return NULL;
}
+ ast_channel_lock(chan);
ast_channel_stage_snapshot(chan);
ast_channel_tech_set(chan, &console_tech);
@@ -444,6 +445,7 @@ 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) {
if (ast_pbx_start(chan)) {
diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c
index 2eba958a8..843254c56 100644
--- a/channels/chan_dahdi.c
+++ b/channels/chan_dahdi.c
@@ -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);
}
/*!
@@ -8916,6 +8918,7 @@ static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpb
return NULL;
}
+ ast_channel_lock(tmp);
ast_channel_stage_snapshot(tmp);
if (callid) {
@@ -9096,6 +9099,7 @@ static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpb
pbx_builtin_setvar_helper(tmp, v->name, v->value);
ast_channel_stage_snapshot_done(tmp);
+ ast_channel_unlock(tmp);
ast_module_ref(ast_module_info->self);
@@ -9614,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)
@@ -9626,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) {
@@ -10389,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) {
diff --git a/channels/chan_gtalk.c b/channels/chan_gtalk.c
index d6a094941..72c01ac8d 100644
--- a/channels/chan_gtalk.c
+++ b/channels/chan_gtalk.c
@@ -1150,6 +1150,7 @@ static struct ast_channel *gtalk_new(struct gtalk *client, struct gtalk_pvt *i,
return NULL;
}
+ ast_channel_lock(tmp);
ast_channel_stage_snapshot(tmp);
ast_channel_tech_set(tmp, &gtalk_tech);
@@ -1226,6 +1227,7 @@ 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)) {
ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp));
@@ -1419,7 +1421,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),
diff --git a/channels/chan_h323.c b/channels/chan_h323.c
index 22dba3c18..7ce098415 100644
--- a/channels/chan_h323.c
+++ b/channels/chan_h323.c
@@ -1061,6 +1061,9 @@ static struct ast_channel *__oh323_new(struct oh323_pvt *pvt, int state, const c
ch = ast_channel_alloc(1, state, cid_num, cid_name, pvt->accountcode, pvt->exten, pvt->context, linkedid, pvt->amaflags, "H323/%s", host);
/* Update usage counter */
ast_module_ref(ast_module_info->self);
+ if (ch) {
+ ast_channel_lock(ch);
+ }
ast_mutex_lock(&pvt->lock);
if (ch) {
ast_channel_tech_set(ch, &oh323_tech);
@@ -1139,6 +1142,7 @@ static struct ast_channel *__oh323_new(struct oh323_pvt *pvt, int state, const c
}
if (pvt->cd.transfer_capability >= 0)
ast_channel_transfercapability_set(ch, pvt->cd.transfer_capability);
+ ast_channel_unlock(ch);
if (state != AST_STATE_DOWN) {
if (ast_pbx_start(ch)) {
ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(ch));
diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c
index e27cc14c6..80081174e 100644
--- a/channels/chan_iax2.c
+++ b/channels/chan_iax2.c
@@ -5689,11 +5689,15 @@ static struct ast_channel *ast_iax2_new(int callno, int state, iax2_format capab
/* Don't hold call lock */
ast_mutex_unlock(&iaxsl[callno]);
tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, linkedid, i->amaflags, "IAX2/%s-%d", i->host, i->callno);
+ if (tmp) {
+ ast_channel_lock(tmp);
+ }
ast_mutex_lock(&iaxsl[callno]);
if (i != iaxs[callno]) {
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]);
}
@@ -5803,6 +5807,7 @@ 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)) {
@@ -12234,7 +12239,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 */
diff --git a/channels/chan_jingle.c b/channels/chan_jingle.c
index 56c15b193..8604d4eb9 100644
--- a/channels/chan_jingle.c
+++ b/channels/chan_jingle.c
@@ -864,6 +864,7 @@ static struct ast_channel *jingle_new(struct jingle *client, struct jingle_pvt *
return NULL;
}
+ ast_channel_lock(tmp);
ast_channel_stage_snapshot(tmp);
ast_channel_tech_set(tmp, &jingle_tech);
@@ -941,6 +942,7 @@ 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)) {
ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp));
@@ -1115,7 +1117,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) {
diff --git a/channels/chan_mgcp.c b/channels/chan_mgcp.c
index 84fb3b225..c10697158 100644
--- a/channels/chan_mgcp.c
+++ b/channels/chan_mgcp.c
@@ -1507,6 +1507,7 @@ static struct ast_channel *mgcp_new(struct mgcp_subchannel *sub, int state, cons
tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, linkedid, i->accountcode, i->exten, i->context, i->amaflags, "MGCP/%s@%s-%d", i->name, i->parent->name, sub->id);
if (tmp) {
+ ast_channel_lock(tmp);
ast_channel_stage_snapshot(tmp);
ast_channel_tech_set(tmp, &mgcp_tech);
ast_format_cap_copy(ast_channel_nativeformats(tmp), i->cap);
@@ -1570,6 +1571,7 @@ 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)) {
@@ -3046,6 +3048,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));
@@ -3054,6 +3057,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);
diff --git a/channels/chan_misdn.c b/channels/chan_misdn.c
index 38197c638..a1b9105e6 100644
--- a/channels/chan_misdn.c
+++ b/channels/chan_misdn.c
@@ -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);
@@ -10228,8 +10238,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);
@@ -10528,7 +10540,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");
diff --git a/channels/chan_motif.c b/channels/chan_motif.c
index 1e7ee3cce..85234ad3a 100644
--- a/channels/chan_motif.c
+++ b/channels/chan_motif.c
@@ -785,6 +785,7 @@ static struct ast_channel *jingle_new(struct jingle_endpoint *endpoint, struct j
if (!(chan = ast_channel_alloc(1, state, S_OR(title, ""), S_OR(cid_name, ""), "", "", "", linkedid, 0, "Motif/%s-%04lx", str, ast_random() & 0xffff))) {
return NULL;
}
+ ast_channel_lock(chan);
ast_channel_stage_snapshot(chan);
@@ -852,6 +853,7 @@ 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;
}
@@ -2412,7 +2414,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) {
diff --git a/channels/chan_nbs.c b/channels/chan_nbs.c
index 1d8c59d4e..41f696207 100644
--- a/channels/chan_nbs.c
+++ b/channels/chan_nbs.c
@@ -223,6 +223,7 @@ static struct ast_channel *nbs_new(struct nbs_pvt *i, int state, const char *lin
struct ast_channel *tmp;
tmp = ast_channel_alloc(1, state, 0, 0, "", "s", context, linkedid, 0, "NBS/%s", i->stream);
if (tmp) {
+ ast_channel_lock(tmp);
ast_channel_tech_set(tmp, &nbs_tech);
ast_channel_set_fd(tmp, 0, nbs_fd(i->nbs));
@@ -239,6 +240,7 @@ static struct ast_channel *nbs_new(struct nbs_pvt *i, int state, const char *lin
ast_channel_language_set(tmp, "");
i->owner = tmp;
i->u = ast_module_user_add(tmp);
+ ast_channel_unlock(tmp);
if (state != AST_STATE_DOWN) {
if (ast_pbx_start(tmp)) {
ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp));
diff --git a/channels/chan_oss.c b/channels/chan_oss.c
index 5ae18f362..92c7374db 100644
--- a/channels/chan_oss.c
+++ b/channels/chan_oss.c
@@ -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);
@@ -829,6 +830,7 @@ static struct ast_channel *oss_new(struct chan_oss_pvt *o, char *ext, char *ctx,
o->owner = c;
ast_module_ref(ast_module_info->self);
ast_jb_configure(c, &global_jbconf);
+ ast_channel_unlock(c);
if (state != AST_STATE_DOWN) {
if (ast_pbx_start(c)) {
ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(c));
diff --git a/channels/chan_phone.c b/channels/chan_phone.c
index c1a24b8b1..ca69a2f69 100644
--- a/channels/chan_phone.c
+++ b/channels/chan_phone.c
@@ -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 */
@@ -898,6 +899,7 @@ static struct ast_channel *phone_new(struct phone_pvt *i, int state, char *cntx,
ast_channel_caller(tmp)->ani.number.valid = 1;
ast_channel_caller(tmp)->ani.number.str = ast_strdup(i->cid_num);
}
+ ast_channel_unlock(tmp);
i->owner = tmp;
ast_module_ref(ast_module_info->self);
diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c
index 80cf270af..12fb45969 100644
--- a/channels/chan_pjsip.c
+++ b/channels/chan_pjsip.c
@@ -577,13 +577,15 @@ static struct ast_channel *chan_pjsip_new(struct ast_sip_session *session, int s
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_lock(chan);
+ ast_channel_stage_snapshot(chan);
+
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));
@@ -632,9 +634,10 @@ 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);
+
+ ast_endpoint_add_channel(session->endpoint->persistent, chan);
return chan;
}
@@ -2030,9 +2033,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);
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index c56f7c4c9..fafe71257 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -8106,6 +8106,7 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit
}
}
+ ast_channel_lock(tmp);
ast_channel_stage_snapshot(tmp);
/* If we sent in a callid, bind it to the channel. */
@@ -8113,7 +8114,6 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit
ast_channel_callid_set(tmp, callid);
}
- ast_channel_lock(tmp);
sip_pvt_lock(i);
ast_channel_cc_params_init(tmp, i->cc_params);
ast_channel_caller(tmp)->id.tag = ast_strdup(i->cid_tag);
diff --git a/channels/chan_skinny.c b/channels/chan_skinny.c
index a65862ff3..191c3cc24 100644
--- a/channels/chan_skinny.c
+++ b/channels/chan_skinny.c
@@ -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);
}
@@ -5424,6 +5426,7 @@ static struct ast_channel *skinny_new(struct skinny_line *l, struct skinny_subli
AST_LIST_INSERT_HEAD(&l->sub, sub, list);
//l->activesub = sub;
}
+ ast_channel_lock(tmp);
ast_channel_stage_snapshot(tmp);
ast_channel_tech_set(tmp, &skinny_tech);
ast_channel_tech_pvt_set(tmp, sub);
@@ -5499,6 +5502,7 @@ 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) {
if (ast_pbx_start(tmp)) {
diff --git a/channels/chan_unistim.c b/channels/chan_unistim.c
index 547cd7c2f..93fd9c502 100644
--- a/channels/chan_unistim.c
+++ b/channels/chan_unistim.c
@@ -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");
@@ -5563,6 +5565,7 @@ static struct ast_channel *unistim_new(struct unistim_subchannel *sub, int state
return NULL;
}
+ ast_channel_lock(tmp);
ast_channel_stage_snapshot(tmp);
ast_format_cap_copy(ast_channel_nativeformats(tmp), l->cap);
@@ -5627,6 +5630,7 @@ 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) {
if (unistimdebug) {
diff --git a/channels/chan_vpb.cc b/channels/chan_vpb.cc
index 12f27249b..6ee0e0618 100644
--- a/channels/chan_vpb.cc
+++ b/channels/chan_vpb.cc
@@ -2439,6 +2439,7 @@ static struct ast_channel *vpb_new(struct vpb_pvt *me, enum ast_channel_state st
tmp = ast_channel_alloc(1, state, 0, 0, "", me->ext, me->context, linkedid, AST_AMA_NONE, "%s", me->dev);
if (tmp) {
+ ast_channel_lock(tmp);
if (use_ast_ind == 1){
ast_channel_tech_set(tmp, &vpb_tech_indicate);
} else {
@@ -2471,6 +2472,7 @@ 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;
diff --git a/channels/sig_analog.c b/channels/sig_analog.c
index bbf7a3c8c..51d3f1495 100644
--- a/channels/sig_analog.c
+++ b/channels/sig_analog.c
@@ -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) {
diff --git a/channels/sig_pri.c b/channels/sig_pri.c
index 5def34c23..48c8c33d7 100644
--- a/channels/sig_pri.c
+++ b/channels/sig_pri.c
@@ -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");
diff --git a/funcs/func_timeout.c b/funcs/func_timeout.c
index 3c2810fd5..e93ce3f62 100644
--- a/funcs/func_timeout.c
+++ b/funcs/func_timeout.c
@@ -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",
diff --git a/include/asterisk/aoc.h b/include/asterisk/aoc.h
index 727362c1f..171fbb300 100644
--- a/include/asterisk/aoc.h
+++ b/include/asterisk/aoc.h
@@ -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 */
diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h
index 7db2b3c3a..29d551b12 100644
--- a/include/asterisk/channel.h
+++ b/include/asterisk/channel.h
@@ -1535,8 +1535,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()
@@ -1552,8 +1551,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
@@ -2337,6 +2335,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.
@@ -3803,6 +3803,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);
@@ -3854,6 +3863,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);
@@ -3937,6 +3950,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 */
@@ -3977,6 +3994,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);
@@ -3992,8 +4013,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);
@@ -4040,6 +4067,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);
diff --git a/include/asterisk/channelstate.h b/include/asterisk/channelstate.h
index f5f7392dd..08f908256 100644
--- a/include/asterisk/channelstate.h
+++ b/include/asterisk/channelstate.h
@@ -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__ */
diff --git a/include/asterisk/stasis_bridges.h b/include/asterisk/stasis_bridges.h
index 9412bf0b7..78b97d188 100644
--- a/include/asterisk/stasis_bridges.h
+++ b/include/asterisk/stasis_bridges.h
@@ -199,6 +199,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.
@@ -213,6 +216,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
@@ -224,6 +230,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
*/
@@ -268,6 +277,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
@@ -331,6 +342,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
@@ -352,6 +365,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
@@ -371,6 +386,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
@@ -392,6 +409,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
@@ -415,6 +434,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
diff --git a/include/asterisk/stasis_channels.h b/include/asterisk/stasis_channels.h
index 519a4b676..65ea660f6 100644
--- a/include/asterisk/stasis_channels.h
+++ b/include/asterisk/stasis_channels.h
@@ -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.
@@ -533,6 +547,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);
diff --git a/main/bridge.c b/main/bridge.c
index 1c3bf16e3..5d6d0632a 100644
--- a/main/bridge.c
+++ b/main/bridge.c
@@ -2497,7 +2497,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),
@@ -2519,6 +2525,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);
}
return res;
}
diff --git a/main/bridge_channel.c b/main/bridge_channel.c
index 96bfb209a..ae33cd056 100644
--- a/main/bridge_channel.c
+++ b/main/bridge_channel.c
@@ -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);
}
diff --git a/main/cel.c b/main/cel.c
index db51361e9..b9f992f6f 100644
--- a/main/cel.c
+++ b/main/cel.c
@@ -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);
}
diff --git a/main/channel.c b/main/channel.c
index 58b50c820..f1bbbda27 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -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;
}
@@ -1261,6 +1263,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;
@@ -1272,6 +1275,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;
}
@@ -1280,9 +1284,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;
}
@@ -2248,7 +2254,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);
@@ -5318,7 +5326,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;
}
@@ -5399,7 +5409,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;
}
@@ -5616,7 +5628,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);
@@ -5677,7 +5691,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)) {
/*
@@ -5949,7 +5965,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);
}
}
diff --git a/main/core_local.c b/main/core_local.c
index 4a047032c..4b1253219 100644
--- a/main/core_local.c
+++ b/main/core_local.c
@@ -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,15 @@ 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_unlock(chan);
+ ao2_unlock(p);
}
int ast_local_setup_bridge(struct ast_channel *ast, struct ast_bridge *bridge, struct ast_channel *swap, struct ast_bridge_features *features)
diff --git a/main/core_unreal.c b/main/core_unreal.c
index 7e457f484..0a4859703 100644
--- a/main/core_unreal.c
+++ b/main/core_unreal.c
@@ -918,8 +918,12 @@ struct ast_channel *ast_unreal_new_channels(struct ast_unreal_pvt *p,
}
if (callid) {
+ ast_channel_lock(owner);
ast_channel_callid_set(owner, callid);
+ ast_channel_unlock(owner);
+ ast_channel_lock(chan);
ast_channel_callid_set(chan, callid);
+ ast_channel_unlock(chan);
}
ast_channel_tech_set(owner, tech);
diff --git a/main/dial.c b/main/dial.c
index 8cc6f9c89..1729af41a 100644
--- a/main/dial.c
+++ b/main/dial.c
@@ -286,6 +286,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");
@@ -315,6 +316,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);
return 0;
}
diff --git a/main/endpoints.c b/main/endpoints.c
index 9eeadfeef..3480a3055 100644
--- a/main/endpoints.c
+++ b/main/endpoints.c
@@ -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;
diff --git a/main/pbx.c b/main/pbx.c
index 99c686371..03b1c4a8e 100644
--- a/main/pbx.c
+++ b/main/pbx.c
@@ -1601,9 +1601,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);
@@ -6101,7 +6103,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);
@@ -10069,6 +10073,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);
}
@@ -10077,6 +10082,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;
@@ -10172,6 +10178,7 @@ static int pbx_outgoing_attempt(const char *type, struct ast_format_cap *cap, co
if (failed) {
char failed_reason[4] = "";
+ ast_channel_lock(failed);
if (!ast_strlen_zero(context)) {
ast_channel_context_set(failed, context);
}
@@ -10184,6 +10191,7 @@ 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)) {
ast_log(LOG_ERROR, "Unable to run PBX on '%s'\n", ast_channel_name(failed));
@@ -10484,10 +10492,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;
}
@@ -10500,10 +10510,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;
}
diff --git a/main/pickup.c b/main/pickup.c
index 7ae6927fa..a415f1672 100644
--- a/main/pickup.c
+++ b/main/pickup.c
@@ -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;
}
diff --git a/main/stasis_bridges.c b/main/stasis_bridges.c
index b92d048bc..dd22710b1 100644
--- a/main/stasis_bridges.c
+++ b/main/stasis_bridges.c
@@ -397,7 +397,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;
}
@@ -579,7 +581,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;
}
@@ -915,7 +919,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;
}
diff --git a/main/stasis_channels.c b/main/stasis_channels.c
index 38aac982e..127106ad9 100644
--- a/main/stasis_channels.c
+++ b/main/stasis_channels.c
@@ -310,14 +310,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;
}
diff --git a/pbx/pbx_realtime.c b/pbx/pbx_realtime.c
index f9f9cb2be..7624d5979 100644
--- a/pbx/pbx_realtime.c
+++ b/pbx/pbx_realtime.c
@@ -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.
diff --git a/res/parking/parking_bridge_features.c b/res/parking/parking_bridge_features.c
index 4f39e2e94..a939fdac7 100644
--- a/res/parking/parking_bridge_features.c
+++ b/res/parking/parking_bridge_features.c
@@ -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 */
diff --git a/res/parking/parking_manager.c b/res/parking/parking_manager.c
index 0c577018a..507273aec 100644
--- a/res/parking/parking_manager.c
+++ b/res/parking/parking_manager.c
@@ -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;
diff --git a/res/res_agi.c b/res/res_agi.c
index ed70356dd..96d3906ac 100644
--- a/res/res_agi.c
+++ b/res/res_agi.c
@@ -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);
diff --git a/res/res_pjsip_refer.c b/res/res_pjsip_refer.c
index 91da22fde..da48e523b 100644
--- a/res/res_pjsip_refer.c
+++ b/res/res_pjsip_refer.c
@@ -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) {
diff --git a/res/res_stasis.c b/res/res_stasis.c
index 691462722..5684d3dd8 100644
--- a/res/res_stasis.c
+++ b/res/res_stasis.c
@@ -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;
}
diff --git a/tests/test_cdr.c b/tests/test_cdr.c
index 57d5b2e32..efbda86c4 100644
--- a/tests/test_cdr.c
+++ b/tests/test_cdr.c
@@ -272,9 +272,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 */
@@ -630,9 +632,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);
@@ -679,9 +683,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);
@@ -754,9 +760,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);
@@ -838,9 +846,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);
@@ -848,9 +858,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));
@@ -926,16 +938,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));
@@ -1049,9 +1065,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);
@@ -1059,18 +1077,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));
@@ -2000,10 +2022,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
@@ -2108,6 +2135,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);
@@ -2116,6 +2144,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));
@@ -2208,6 +2237,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);
@@ -2216,6 +2246,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);
@@ -2385,7 +2416,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);
diff --git a/tests/test_cel.c b/tests/test_cel.c
index 0aa8b601c..a90dfbf3e 100644
--- a/tests/test_cel.c
+++ b/tests/test_cel.c
@@ -1551,10 +1551,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);
@@ -1675,7 +1679,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;
}
diff --git a/tests/test_stasis_channels.c b/tests/test_stasis_channels.c
index 45f1e2ba3..b7c9fe2c5 100644
--- a/tests/test_stasis_channels.c
+++ b/tests/test_stasis_channels.c
@@ -77,10 +77,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);
@@ -129,7 +131,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);
@@ -196,9 +200,15 @@ AST_TEST_DEFINE(multi_channel_blob_snapshots)
chan_charlie = ast_channel_alloc(0, AST_STATE_DOWN, "300", "Bob", "300", "300", "default", NULL, 0, "TEST/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"));
@@ -252,7 +262,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_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);