summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Harwell <kharwell@digium.com>2013-12-18 20:33:37 +0000
committerKevin Harwell <kharwell@digium.com>2013-12-18 20:33:37 +0000
commit28c0cb28d0815e5e59ab99b60ac6b50e1ed9cbae (patch)
treeb42967f4899ba28aea79b9a11827c814b95b62c8
parent86b5e11607e2e3b7dcfb0b72d41b492ce868f31c (diff)
channel locking: Add locking for channel snapshot creation
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
-rw-r--r--addons/chan_mobile.c1
-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.c1
-rw-r--r--channels/chan_console.c1
-rw-r--r--channels/chan_dahdi.c6
-rw-r--r--channels/chan_gtalk.c3
-rw-r--r--channels/chan_iax2.c3
-rw-r--r--channels/chan_jingle.c3
-rw-r--r--channels/chan_mgcp.c3
-rw-r--r--channels/chan_misdn.c14
-rw-r--r--channels/chan_motif.c3
-rw-r--r--channels/chan_oss.c1
-rw-r--r--channels/chan_phone.c1
-rw-r--r--channels/chan_pjsip.c3
-rw-r--r--channels/chan_skinny.c3
-rw-r--r--channels/chan_unistim.c5
-rw-r--r--channels/chan_vpb.cc1
-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.c30
-rw-r--r--main/dial.c2
-rw-r--r--main/endpoints.c2
-rw-r--r--main/pbx.c11
-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
53 files changed, 340 insertions, 38 deletions
diff --git a/addons/chan_mobile.c b/addons/chan_mobile.c
index a76d778c4..197974ac5 100644
--- a/addons/chan_mobile.c
+++ b/addons/chan_mobile.c
@@ -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;
diff --git a/addons/chan_ooh323.c b/addons/chan_ooh323.c
index 3aea0d49d..8111b712e 100644
--- a/addons/chan_ooh323.c
+++ b/addons/chan_ooh323.c
@@ -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);
diff --git a/apps/app_agent_pool.c b/apps/app_agent_pool.c
index 2b0d1f8b8..a44c75d46 100644
--- a/apps/app_agent_pool.c
+++ b/apps/app_agent_pool.c
@@ -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;
diff --git a/apps/app_confbridge.c b/apps/app_confbridge.c
index 300d2c7e1..01ae4256c 100644
--- a/apps/app_confbridge.c
+++ b/apps/app_confbridge.c
@@ -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);
diff --git a/apps/app_dial.c b/apps/app_dial.c
index fdbe05692..99d00f13c 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 feea3b6c5..4621d15b4 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 d9f0f85d3..e1c8a0042 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 4dffbbef0..36692981b 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 1d2d5f9f2..a68a0b2c4 100644
--- a/channels/chan_alsa.c
+++ b/channels/chan_alsa.c
@@ -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) {
diff --git a/channels/chan_console.c b/channels/chan_console.c
index e37b565c5..083af7c06 100644
--- a/channels/chan_console.c
+++ b/channels/chan_console.c
@@ -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) {
diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c
index 636d8863f..e4f1c0c85 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);
}
/*!
@@ -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) {
diff --git a/channels/chan_gtalk.c b/channels/chan_gtalk.c
index bec440103..60213d3d2 100644
--- a/channels/chan_gtalk.c
+++ b/channels/chan_gtalk.c
@@ -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),
diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c
index b89ae824b..447860bd1 100644
--- a/channels/chan_iax2.c
+++ b/channels/chan_iax2.c
@@ -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 */
diff --git a/channels/chan_jingle.c b/channels/chan_jingle.c
index c1c502687..410cb324f 100644
--- a/channels/chan_jingle.c
+++ b/channels/chan_jingle.c
@@ -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) {
diff --git a/channels/chan_mgcp.c b/channels/chan_mgcp.c
index a6f75e6c3..aaed68fea 100644
--- a/channels/chan_mgcp.c
+++ b/channels/chan_mgcp.c
@@ -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);
diff --git a/channels/chan_misdn.c b/channels/chan_misdn.c
index 6dd9adf6a..02b525039 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);
@@ -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");
diff --git a/channels/chan_motif.c b/channels/chan_motif.c
index 2c2b27007..248f81120 100644
--- a/channels/chan_motif.c
+++ b/channels/chan_motif.c
@@ -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) {
diff --git a/channels/chan_oss.c b/channels/chan_oss.c
index 3a52ac9db..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);
diff --git a/channels/chan_phone.c b/channels/chan_phone.c
index ba14a435e..94a40ca1a 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 */
diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c
index cd209d243..a560d7706 100644
--- a/channels/chan_pjsip.c
+++ b/channels/chan_pjsip.c
@@ -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);
diff --git a/channels/chan_skinny.c b/channels/chan_skinny.c
index bb270d6a9..49f2c84f6 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);
}
@@ -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) {
diff --git a/channels/chan_unistim.c b/channels/chan_unistim.c
index 21bbbc1e8..bc79f5ee0 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");
@@ -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) {
diff --git a/channels/chan_vpb.cc b/channels/chan_vpb.cc
index 39d78cc33..5ea24ccc1 100644
--- a/channels/chan_vpb.cc
+++ b/channels/chan_vpb.cc
@@ -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;
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 51530a82b..80ed7458c 100644
--- a/include/asterisk/channel.h
+++ b/include/asterisk/channel.h
@@ -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);
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 2d15a3332..72bf59948 100644
--- a/include/asterisk/stasis_bridges.h
+++ b/include/asterisk/stasis_bridges.h
@@ -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
diff --git a/include/asterisk/stasis_channels.h b/include/asterisk/stasis_channels.h
index 8c27803df..9c64c1c49 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.
@@ -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);
diff --git a/main/bridge.c b/main/bridge.c
index 8fd7847ec..8acf260d1 100644
--- a/main/bridge.c
+++ b/main/bridge.c
@@ -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;
}
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 418e6a772..669b81529 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;
}
@@ -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);
}
}
diff --git a/main/core_local.c b/main/core_local.c
index 4a047032c..edf28399b 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,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)
diff --git a/main/dial.c b/main/dial.c
index ca0b9c8d1..6ff0e7f7d 100644
--- a/main/dial.c
+++ b/main/dial.c
@@ -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);
diff --git a/main/endpoints.c b/main/endpoints.c
index 4be4eb31b..9cc0178e0 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 726677f4a..1e6a24625 100644
--- a/main/pbx.c
+++ b/main/pbx.c
@@ -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;
}
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 7f6679b00..b8d4ae8e1 100644
--- a/main/stasis_bridges.c
+++ b/main/stasis_bridges.c
@@ -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;
}
diff --git a/main/stasis_channels.c b/main/stasis_channels.c
index 8a39bdfcb..677527ba3 100644
--- a/main/stasis_channels.c
+++ b/main/stasis_channels.c
@@ -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;
}
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 ba0ffddfb..bf211a2bd 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 60baa6510..9d8c23618 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 71a18a07f..32de9a041 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 e70a0641b..946b57074 100644
--- a/tests/test_cdr.c
+++ b/tests/test_cdr.c
@@ -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);
diff --git a/tests/test_cel.c b/tests/test_cel.c
index 7da4f9ee8..62a3288e0 100644
--- a/tests/test_cel.c
+++ b/tests/test_cel.c
@@ -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;
}
diff --git a/tests/test_stasis_channels.c b/tests/test_stasis_channels.c
index de445458c..28961ed13 100644
--- a/tests/test_stasis_channels.c
+++ b/tests/test_stasis_channels.c
@@ -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);