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/


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/11@432526 65c4cc65-6c06-0410-ace0-fbb531ad65f3
changes/61/61/1
Richard Mudgett 10 years ago
parent a0dc90c5b8
commit 2befe82721

@ -15823,6 +15823,17 @@ static int sip_poke_peer_s(const void *data)
return 0; 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 */ /*! \brief Get registration details from Asterisk DB */
static void reg_source_db(struct sip_peer *peer) static void reg_source_db(struct sip_peer *peer)
{ {
@ -20413,24 +20424,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) static char *sip_show_sched(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{ {
struct ast_str *cbuf; struct ast_str *cbuf;
struct ast_cb_names cbnames = {9, { "retrans_pkt", struct ast_cb_names cbnames = {
"__sip_autodestruct", 10,
"expire_register", {
"auto_congest", "retrans_pkt",
"sip_reg_timeout", "__sip_autodestruct",
"sip_poke_peer_s", "expire_register",
"sip_poke_noanswer", "auto_congest",
"sip_reregister", "sip_reg_timeout",
"sip_reinvite_retry"}, "sip_poke_peer_s",
{ retrans_pkt, "sip_poke_peer_now",
__sip_autodestruct, "sip_poke_noanswer",
expire_register, "sip_reregister",
auto_congest, "sip_reinvite_retry"
sip_reg_timeout, },
sip_poke_peer_s, {
sip_poke_noanswer, retrans_pkt,
sip_reregister, __sip_autodestruct,
sip_reinvite_retry}}; 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) { switch (cmd) {
case CLI_INIT: case CLI_INIT:
@ -31357,7 +31377,17 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
/* Startup regular pokes */ /* Startup regular pokes */
if (!devstate_only && enablepoke) { 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"));
} }
} }

Loading…
Cancel
Save