mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-02 02:18:31 +00:00
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
This commit is contained in:
@@ -16011,6 +16011,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)
|
||||||
{
|
{
|
||||||
@@ -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)
|
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:
|
||||||
@@ -31084,7 +31104,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"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user