Author: rmudgett
Date: Fri Mar  6 13:17:45 2015
New Revision: 432526

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=432526
Log:
chan_sip: Fix realtime locking inversion when poking a just built peer.

When a realtime peer is built it can cause a locking inversion when the
just built peer is poked.  If the CLI command "sip show channels" is
periodically executed then a deadlock can happen because of the locking
inversion.

* Push the peer poke off onto the scheduler thread to avoid the locking
inversion of the just built realtime peer.

AST-1540
ASTERISK-24838 #close
Reported by: Richard Mudgett

Review: https://reviewboard.asterisk.org/r/4454/

Modified:
    branches/11/channels/chan_sip.c

Modified: branches/11/channels/chan_sip.c
URL: 
http://svnview.digium.com/svn/asterisk/branches/11/channels/chan_sip.c?view=diff&rev=432526&r1=432525&r2=432526
==============================================================================
--- branches/11/channels/chan_sip.c (original)
+++ branches/11/channels/chan_sip.c Fri Mar  6 13:17:45 2015
@@ -15823,6 +15823,17 @@
        return 0;
 }
 
+static int sip_poke_peer_now(const void *data)
+{
+       struct sip_peer *peer = (struct sip_peer *) data;
+
+       peer->pokeexpire = -1;
+       sip_poke_peer(peer, 0);
+       sip_unref_peer(peer, "removing poke peer ref");
+
+       return 0;
+}
+
 /*! \brief Get registration details from Asterisk DB */
 static void reg_source_db(struct sip_peer *peer)
 {
@@ -20413,24 +20424,33 @@
 static char *sip_show_sched(struct ast_cli_entry *e, int cmd, struct 
ast_cli_args *a)
 {
        struct ast_str *cbuf;
-       struct ast_cb_names cbnames = {9, { "retrans_pkt",
-                                        "__sip_autodestruct",
-                                        "expire_register",
-                                        "auto_congest",
-                                        "sip_reg_timeout",
-                                        "sip_poke_peer_s",
-                                        "sip_poke_noanswer",
-                                        "sip_reregister",
-                                        "sip_reinvite_retry"},
-                                                                  { 
retrans_pkt,
-                                     __sip_autodestruct,
-                                     expire_register,
-                                     auto_congest,
-                                     sip_reg_timeout,
-                                     sip_poke_peer_s,
-                                     sip_poke_noanswer,
-                                     sip_reregister,
-                                     sip_reinvite_retry}};
+       struct ast_cb_names cbnames = {
+               10,
+               {
+                       "retrans_pkt",
+                       "__sip_autodestruct",
+                       "expire_register",
+                       "auto_congest",
+                       "sip_reg_timeout",
+                       "sip_poke_peer_s",
+                       "sip_poke_peer_now",
+                       "sip_poke_noanswer",
+                       "sip_reregister",
+                       "sip_reinvite_retry"
+               },
+               {
+                       retrans_pkt,
+                       __sip_autodestruct,
+                       expire_register,
+                       auto_congest,
+                       sip_reg_timeout,
+                       sip_poke_peer_s,
+                       sip_poke_peer_now,
+                       sip_poke_noanswer,
+                       sip_reregister,
+                       sip_reinvite_retry
+               }
+       };
        
        switch (cmd) {
        case CLI_INIT:
@@ -31357,7 +31377,17 @@
 
                /* Startup regular pokes */
                if (!devstate_only && enablepoke) {
-                       sip_poke_peer(peer, 0);
+                       /*
+                        * We cannot poke the peer now in this thread without
+                        * a lock inversion so pass it off to the scheduler
+                        * thread.
+                        */
+                       AST_SCHED_REPLACE_UNREF(peer->pokeexpire, sched,
+                               0, /* Poke the peer ASAP */
+                               sip_poke_peer_now, peer,
+                               sip_unref_peer(_data, "removing poke peer ref"),
+                               sip_unref_peer(peer, "removing poke peer ref"),
+                               sip_ref_peer(peer, "adding poke peer ref"));
                }
        }
 


-- 
_____________________________________________________________________
-- Bandwidth and Colocation Provided by http://www.api-digital.com --

svn-commits mailing list
To UNSUBSCRIBE or update options visit:
   http://lists.digium.com/mailman/listinfo/svn-commits

Reply via email to