From 13e715b30c1e4fff81d6c42896a5ef5ade29b74a Mon Sep 17 00:00:00 2001 From: Richard Mudgett Date: Fri, 6 Mar 2015 19:31:21 +0000 Subject: 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/ ........ Merged revisions 432526 from http://svn.asterisk.org/svn/asterisk/branches/11 git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/13@432528 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- channels/chan_sip.c | 68 ++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 49 insertions(+), 19 deletions(-) (limited to 'channels/chan_sip.c') diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 3354517f6..9826f42a3 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -16011,6 +16011,17 @@ static int sip_poke_peer_s(const void *data) 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) { @@ -20688,24 +20699,33 @@ static char *sip_show_user(struct ast_cli_entry *e, int cmd, struct ast_cli_args 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: @@ -31084,7 +31104,17 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str /* 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")); } } -- cgit v1.2.3