summaryrefslogtreecommitdiff
path: root/channels
diff options
context:
space:
mode:
authorRichard Mudgett <rmudgett@digium.com>2015-03-06 19:34:35 +0000
committerRichard Mudgett <rmudgett@digium.com>2015-03-06 19:34:35 +0000
commitf1ab2c5e8b77473b76391bbdc2bf5b12f32f0372 (patch)
tree7434d13c134564f959f1a0b6378067c122734ff5 /channels
parent5c3e33b3ca5a726162745c4fb5435d98f737a3b7 (diff)
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 ........ Merged revisions 432528 from http://svn.asterisk.org/svn/asterisk/branches/13 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@432529 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'channels')
-rw-r--r--channels/chan_sip.c68
1 files changed, 49 insertions, 19 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index cf2cd097c..13c55462c 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -16020,6 +16020,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)
{
@@ -20697,24 +20708,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:
@@ -31102,7 +31122,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"));
}
}