From: Richard Mudgett Date: Sat, 29 Apr 2017 21:18:22 +0000 (-0500) Subject: rtp_engine.c: Fix deadlock potential copying RTP payload maps. X-Git-Tag: 13.16.0-rc1~21^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=02234e920ce7c5534683fbfd9273eff56595d677;p=thirdparty%2Fasterisk.git rtp_engine.c: Fix deadlock potential copying RTP payload maps. There is a theoretical potential to deadlock in ast_rtp_codecs_payloads_copy() because it locks two different ast_rtp_codecs locks. It is theoretical because the callers of the function are either copying between a local ast_rtp_codecs struct and a RTP instance of the ast_rtp_codecs struct. Or they are copying between the caller and callee channel RTP instances before initiating the call to the callee. Neither of these situations could actually result in a deadlock because there cannot be another thread involved at the time. * Add deadlock avoidance code to ast_rtp_codecs_payloads_copy() since it locks two ast_rtp_codecs locks to perform a copy. This only affects v13 since this deadlock avoidance code is already in newer branches. Change-Id: I1aa0b168f94049bd59bbd74a85bd1e78718f09e5 --- diff --git a/main/rtp_engine.c b/main/rtp_engine.c index f1da873d4a..33770877cf 100644 --- a/main/rtp_engine.c +++ b/main/rtp_engine.c @@ -708,9 +708,15 @@ void ast_rtp_codecs_payloads_copy(struct ast_rtp_codecs *src, struct ast_rtp_cod { int i; - ast_rwlock_rdlock(&src->codecs_lock); ast_rwlock_wrlock(&dest->codecs_lock); + /* Deadlock avoidance because of held write lock. */ + while (ast_rwlock_tryrdlock(&src->codecs_lock)) { + ast_rwlock_unlock(&dest->codecs_lock); + sched_yield(); + ast_rwlock_wrlock(&dest->codecs_lock); + } + for (i = 0; i < AST_VECTOR_SIZE(&src->payloads); i++) { struct ast_rtp_payload_type *type; @@ -732,8 +738,8 @@ void ast_rtp_codecs_payloads_copy(struct ast_rtp_codecs *src, struct ast_rtp_cod } } dest->framing = src->framing; - ast_rwlock_unlock(&dest->codecs_lock); ast_rwlock_unlock(&src->codecs_lock); + ast_rwlock_unlock(&dest->codecs_lock); } void ast_rtp_codecs_payloads_set_m_type(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, int payload)