summaryrefslogtreecommitdiff
path: root/include/asterisk
diff options
context:
space:
mode:
authorzuul <zuul@gerrit.asterisk.org>2017-03-21 19:47:25 -0500
committerGerrit Code Review <gerrit2@gerrit.digium.api>2017-03-21 19:47:25 -0500
commitd7ba743329829c5fddb0040708d80461e34e0677 (patch)
treeb7a6ff3f7dc128de62ea3f03fa7b0e49ea27e7e8 /include/asterisk
parent72ae513f1529a1ac0c55c069db4e06f5732103ef (diff)
parentadad6020beb2aae1f5535bad4c0ff6ea73026848 (diff)
Merge "autochan/mixmonitor/chanspy: Fix unsafe channel locking and references." into 13
Diffstat (limited to 'include/asterisk')
-rw-r--r--include/asterisk/autochan.h20
1 files changed, 13 insertions, 7 deletions
diff --git a/include/asterisk/autochan.h b/include/asterisk/autochan.h
index 319c203ab..128377b57 100644
--- a/include/asterisk/autochan.h
+++ b/include/asterisk/autochan.h
@@ -32,6 +32,7 @@
struct ast_autochan {
struct ast_channel *chan;
AST_LIST_ENTRY(ast_autochan) list;
+ ast_mutex_t lock;
};
/*!
@@ -61,19 +62,24 @@ struct ast_autochan {
* 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
+ * While chan is locked, the autochan structure is guaranteed to keep the
* same channel.
*/
+/*!
+ * \brief Lock the autochan's channel lock.
+ *
+ * \note We must do deadlock avoidance because the channel lock is
+ * superior to the autochan lock in locking order.
+ */
#define ast_autochan_channel_lock(autochan) \
do { \
- struct ast_channel *autochan_chan = autochan->chan; \
- ast_channel_lock(autochan_chan); \
- if (autochan->chan == autochan_chan) { \
- break; \
+ ast_mutex_lock(&(autochan)->lock); \
+ while (ast_channel_trylock((autochan)->chan)) { \
+ DEADLOCK_AVOIDANCE(&(autochan)->lock); \
} \
- ast_channel_unlock(autochan_chan); \
- } while (1)
+ ast_mutex_unlock(&(autochan)->lock); \
+ } while (0)
#define ast_autochan_channel_unlock(autochan) \
ast_channel_unlock(autochan->chan)