From 8e8b329e14ad2e4d747c4c4eb33c118305401aee Mon Sep 17 00:00:00 2001 From: Mark Michelson Date: Tue, 3 Dec 2013 17:07:29 +0000 Subject: 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 --- apps/app_agent_pool.c | 4 ++++ apps/app_confbridge.c | 2 ++ apps/app_dial.c | 16 +++++++++++++--- apps/app_disa.c | 5 ++++- apps/app_meetme.c | 2 ++ apps/app_queue.c | 13 ++++++++++++- apps/app_userevent.c | 2 ++ apps/app_voicemail.c | 5 ++++- 8 files changed, 43 insertions(+), 6 deletions(-) (limited to 'apps') 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"); -- cgit v1.2.3