diff --git a/apps/app_chanspy.c b/apps/app_chanspy.c index 31a1e18..78733ef 100644 --- a/apps/app_chanspy.c +++ b/apps/app_chanspy.c @@ -532,12 +532,12 @@ static int attach_barge(struct ast_autochan *spyee_autochan, return -1; } - ast_channel_lock(internal_bridge_autochan->chan); + ast_autochan_channel_lock(internal_bridge_autochan); if (start_spying(internal_bridge_autochan, spyer_name, bridge_whisper_audiohook)) { ast_log(LOG_WARNING, "Unable to attach barge audiohook on spyee '%s'. Barge mode disabled.\n", name); retval = -1; } - ast_channel_unlock(internal_bridge_autochan->chan); + ast_autochan_channel_unlock(internal_bridge_autochan); *spyee_bridge_autochan = internal_bridge_autochan; @@ -569,9 +569,9 @@ static int channel_spy(struct ast_channel *chan, struct ast_autochan *spyee_auto return 0; } - ast_channel_lock(spyee_autochan->chan); + ast_autochan_channel_lock(spyee_autochan); name = ast_strdupa(ast_channel_name(spyee_autochan->chan)); - ast_channel_unlock(spyee_autochan->chan); + ast_autochan_channel_unlock(spyee_autochan); ast_verb(2, "Spying on channel %s\n", name); /*** DOCUMENTATION diff --git a/include/asterisk/autochan.h b/include/asterisk/autochan.h index 2ace4f2..e62a299 100644 --- a/include/asterisk/autochan.h +++ b/include/asterisk/autochan.h @@ -56,8 +56,28 @@ struct ast_autochan { * to save off the pointer using ast_channel_ref and to unref the channel when you * are finished with the pointer. If you do not do this and a masquerade occurs on * the channel, then it is possible that your saved pointer will become invalid. + * + * 3. If you want to lock the autochan->chan channel, be sure to use + * ast_autochan_channel_lock and ast_autochan_channel_unlock. An attempt to lock + * the autochan->chan directly may result in it being changed after you've + * retrieved the value of chan, but before you've had a chance to lock it. + * First when chan is locked, the autochan structure is guaranteed to keep the + * same channel. */ +#define ast_autochan_channel_lock(autochan) \ + do { \ + struct ast_channel *autochan_chan = autochan->chan; \ + ast_channel_lock(autochan_chan); \ + if (autochan->chan != autochan_chan) { \ + ast_channel_unlock(autochan_chan); \ + continue; \ + } \ + } while(0); + +#define ast_autochan_channel_unlock(autochan) \ + ast_channel_unlock(autochan->chan); + /*! * \brief set up a new ast_autochan structure * diff --git a/main/autochan.c b/main/autochan.c index 7da249a..b8c1eab 100644 --- a/main/autochan.c +++ b/main/autochan.c @@ -51,7 +51,7 @@ struct ast_autochan *ast_autochan_setup(struct ast_channel *chan) autochan->chan = ast_channel_ref(chan); - ast_channel_lock(autochan->chan); + ast_channel_lock(autochan->chan); /* autochan was still private, no need for ast_autochan_channel_lock() */ AST_LIST_INSERT_TAIL(ast_channel_autochans(autochan->chan), autochan, list); ast_channel_unlock(autochan->chan); @@ -64,7 +64,7 @@ void ast_autochan_destroy(struct ast_autochan *autochan) { struct ast_autochan *autochan_iter; - ast_channel_lock(autochan->chan); + ast_autochan_channel_lock(autochan); AST_LIST_TRAVERSE_SAFE_BEGIN(ast_channel_autochans(autochan->chan), autochan_iter, list) { if (autochan_iter == autochan) { AST_LIST_REMOVE_CURRENT(list); @@ -73,7 +73,7 @@ void ast_autochan_destroy(struct ast_autochan *autochan) } } AST_LIST_TRAVERSE_SAFE_END; - ast_channel_unlock(autochan->chan); + ast_autochan_channel_unlock(autochan); autochan->chan = ast_channel_unref(autochan->chan);