Resolve deadlock between SIP registration and channel based functions
[asterisk/asterisk.git] / channels / chan_sip.c
index 28e8d4d..82a8519 100644 (file)
@@ -16131,7 +16131,9 @@ static enum parse_register_result parse_register_contact(struct sip_pvt *pvt, st
                ast_verb(3, "Registered SIP '%s' at %s\n", peer->name,
                        ast_sockaddr_stringify(&peer->addr));
        }
                ast_verb(3, "Registered SIP '%s' at %s\n", peer->name,
                        ast_sockaddr_stringify(&peer->addr));
        }
+       sip_pvt_unlock(pvt);
        sip_poke_peer(peer, 0);
        sip_poke_peer(peer, 0);
+       sip_pvt_lock(pvt);
        register_peer_exten(peer, 1);
 
        /* Save User agent */
        register_peer_exten(peer, 1);
 
        /* Save User agent */
@@ -17163,9 +17165,9 @@ static enum check_auth_result register_verify(struct sip_pvt *p, struct ast_sock
        }
        if (!res) {
                if (send_mwi) {
        }
        if (!res) {
                if (send_mwi) {
-                       ao2_unlock(p);
+                       sip_pvt_unlock(p);
                        sip_send_mwi_to_peer(peer, 0);
                        sip_send_mwi_to_peer(peer, 0);
-                       ao2_lock(p);
+                       sip_pvt_lock(p);
                } else {
                        update_peer_lastmsgssent(peer, -1, 0);
                }
                } else {
                        update_peer_lastmsgssent(peer, -1, 0);
                }
@@ -29611,6 +29613,9 @@ static int sip_poke_noanswer(const void *data)
 \note  This is done with 60 seconds between each ping,
        unless forced by cli or manager. If peer is unreachable,
        we check every 10th second by default.
 \note  This is done with 60 seconds between each ping,
        unless forced by cli or manager. If peer is unreachable,
        we check every 10th second by default.
+\note Do *not* hold a pvt lock while calling this function.
+       This function calls sip_alloc, which can cause a deadlock
+       if another sip_pvt is held.
 */
 static int sip_poke_peer(struct sip_peer *peer, int force)
 {
 */
 static int sip_poke_peer(struct sip_peer *peer, int force)
 {