]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
rtp_engine.c: Fix deadlock potential copying RTP payload maps.
authorRichard Mudgett <rmudgett@digium.com>
Sat, 29 Apr 2017 21:18:22 +0000 (16:18 -0500)
committerRichard Mudgett <rmudgett@digium.com>
Sat, 29 Apr 2017 23:12:49 +0000 (18:12 -0500)
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

main/rtp_engine.c

index f1da873d4a07be888d8515d4cb599c38fa616bb9..33770877cfe21f391ffad224d5fb34632aeacd2c 100644 (file)
@@ -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)