[asterisk-commits] rmudgett: branch 10 r336978 - in /branches/10: ./ channels/sig_ss7.c
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Tue Sep 20 13:14:42 CDT 2011
Author: rmudgett
Date: Tue Sep 20 13:14:40 2011
New Revision: 336978
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=336978
Log:
Merged revisions 336977 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.8
........
r336977 | rmudgett | 2011-09-20 13:12:17 -0500 (Tue, 20 Sep 2011) | 21 lines
Fix deadlock from not releasing SS7 linkset lock.
sig_ss7_hangup() failed to release the SS7 linkset lock if the call had
the alreadyhungup flag set.
* Made unlock the SS7 linkset lock in sig_ss7_hangup() if the
alreadyhungup flag is set.
* Made ss7_start_call() not hold any locks while creating the channel for
an incoming call to prevent deadlock.
* Made ss7_grab() a void function, since it could never fail, to simplify
calling code.
* Made obtain the channel lock to do softhangup in some places.
Patches:
jira_ast_668_v1.8.patch (license #5621) patch uploaded by rmudgett
JIRA AST-668
........
Modified:
branches/10/ (props changed)
branches/10/channels/sig_ss7.c
Propchange: branches/10/
------------------------------------------------------------------------------
Binary property 'branch-1.8-merged' - no diff available.
Modified: branches/10/channels/sig_ss7.c
URL: http://svnview.digium.com/svn/asterisk/branches/10/channels/sig_ss7.c?view=diff&rev=336978&r1=336977&r2=336978
==============================================================================
--- branches/10/channels/sig_ss7.c (original)
+++ branches/10/channels/sig_ss7.c Tue Sep 20 13:14:40 2011
@@ -454,19 +454,26 @@
}
/*
- * Release the SS7 lock while we create the channel
- * so other threads can send messages.
+ * Release the SS7 lock while we create the channel so other
+ * threads can send messages. We must also release the private
+ * lock to prevent deadlock while creating the channel.
*/
ast_mutex_unlock(&linkset->lock);
+ sig_ss7_unlock_private(p);
c = sig_ss7_new_ast_channel(p, AST_STATE_RING, law, 0, p->exten, NULL);
if (!c) {
ast_log(LOG_WARNING, "Unable to start PBX on CIC %d\n", p->cic);
ast_mutex_lock(&linkset->lock);
+ sig_ss7_lock_private(p);
isup_rel(linkset->ss7, p->ss7call, -1);
p->call_level = SIG_SS7_CALL_LEVEL_IDLE;
p->alreadyhungup = 1;
return;
}
+
+ /* Hold the channel and private lock while we setup the channel. */
+ ast_channel_lock(c);
+ sig_ss7_lock_private(p);
sig_ss7_set_echocanceller(p, 1);
@@ -549,13 +556,19 @@
p->generic_name[0] = 0;
}
+ sig_ss7_unlock_private(p);
+ ast_channel_unlock(c);
+
if (ast_pbx_start(c)) {
ast_log(LOG_WARNING, "Unable to start PBX on %s (CIC %d)\n", c->name, p->cic);
ast_hangup(c);
} else {
ast_verb(3, "Accepting call to '%s' on CIC %d\n", p->exten, p->cic);
}
+
+ /* Must return with linkset and private lock. */
ast_mutex_lock(&linkset->lock);
+ sig_ss7_lock_private(p);
}
static void ss7_apply_plan_to_number(char *buf, size_t size, const struct sig_ss7_linkset *ss7, const char *number, const unsigned nai)
@@ -739,9 +752,12 @@
sig_ss7_set_remotelyblocked(p, 0);
dpc = p->dpc;
isup_set_call_dpc(e->rsc.call, dpc);
+ sig_ss7_lock_owner(linkset, chanpos);
p->ss7call = NULL;
- if (p->owner)
- p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
+ if (p->owner) {
+ ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_DEV);
+ ast_channel_unlock(p->owner);
+ }
sig_ss7_unlock_private(p);
isup_rlc(ss7, e->rsc.call);
break;
@@ -912,9 +928,11 @@
}
p = linkset->pvts[chanpos];
sig_ss7_lock_private(p);
+ sig_ss7_lock_owner(linkset, chanpos);
if (p->owner) {
p->owner->hangupcause = e->rel.cause;
- p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
+ ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_DEV);
+ ast_channel_unlock(p->owner);
} else {
ast_log(LOG_WARNING, "REL on channel (CIC %d) without owner!\n", p->cic);
}
@@ -1088,8 +1106,8 @@
else
ast_log(LOG_NOTICE, "Received RLC out and we haven't sent REL. Ignoring.\n");
sig_ss7_unlock_private(p);
- }
- break;
+ }
+ break;
case ISUP_EVENT_FAA:
chanpos = ss7_find_cic(linkset, e->faa.cic, e->faa.opc);
if (chanpos < 0) {
@@ -1122,7 +1140,7 @@
ast_mutex_unlock(&ss7->lock);
}
-static inline int ss7_grab(struct sig_ss7_chan *pvt, struct sig_ss7_linkset *ss7)
+static void ss7_grab(struct sig_ss7_chan *pvt, struct sig_ss7_linkset *ss7)
{
int res;
/* Grab the lock first */
@@ -1135,7 +1153,6 @@
/* Then break the poll */
if (ss7->master != AST_PTHREADT_NULL)
pthread_kill(ss7->master, SIGURG);
- return 0;
}
/*!
@@ -1302,10 +1319,7 @@
l = NULL;
}
- if (ss7_grab(p, p->ss7)) {
- ast_log(LOG_WARNING, "Failed to grab SS7!\n");
- return -1;
- }
+ ss7_grab(p, p->ss7);
p->ss7call = isup_new_call(p->ss7->ss7);
if (!p->ss7call) {
@@ -1428,24 +1442,22 @@
p->exten[0] = '\0';
/* Perform low level hangup if no owner left */
if (p->ss7call) {
- if (!ss7_grab(p, p->ss7)) {
- if (!p->alreadyhungup) {
- const char *cause = pbx_builtin_getvar_helper(ast,"SS7_CAUSE");
- int icause = ast->hangupcause ? ast->hangupcause : -1;
-
- if (cause) {
- if (atoi(cause))
- icause = atoi(cause);
- }
- isup_rel(p->ss7->ss7, p->ss7call, icause);
- ss7_rel(p->ss7);
- p->alreadyhungup = 1;
- } else
- ast_log(LOG_WARNING, "Trying to hangup twice!\n");
+ ss7_grab(p, p->ss7);
+ if (!p->alreadyhungup) {
+ const char *cause = pbx_builtin_getvar_helper(ast,"SS7_CAUSE");
+ int icause = ast->hangupcause ? ast->hangupcause : -1;
+
+ if (cause) {
+ if (atoi(cause)) {
+ icause = atoi(cause);
+ }
+ }
+ isup_rel(p->ss7->ss7, p->ss7call, icause);
+ p->alreadyhungup = 1;
} else {
- ast_log(LOG_WARNING, "Unable to grab SS7 on CIC %d\n", p->cic);
- res = -1;
- }
+ ast_log(LOG_WARNING, "Trying to hangup twice!\n");
+ }
+ ss7_rel(p->ss7);
}
return res;
@@ -1465,16 +1477,12 @@
{
int res;
- if (!ss7_grab(p, p->ss7)) {
- if (p->call_level < SIG_SS7_CALL_LEVEL_CONNECT) {
- p->call_level = SIG_SS7_CALL_LEVEL_CONNECT;
- }
- res = isup_anm(p->ss7->ss7, p->ss7call);
- ss7_rel(p->ss7);
- } else {
- ast_log(LOG_WARNING, "Unable to grab SS7 on span %d\n", p->ss7->span);
- res = -1;
- }
+ ss7_grab(p, p->ss7);
+ if (p->call_level < SIG_SS7_CALL_LEVEL_CONNECT) {
+ p->call_level = SIG_SS7_CALL_LEVEL_CONNECT;
+ }
+ res = isup_anm(p->ss7->ss7, p->ss7call);
+ ss7_rel(p->ss7);
return res;
}
More information about the asterisk-commits
mailing list