mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-03 03:20:57 +00:00
Merged revisions 336978 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/10 ................ r336978 | rmudgett | 2011-09-20 13:14:40 -0500 (Tue, 20 Sep 2011) | 28 lines 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 ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@336988 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -454,20 +454,27 @@ static void ss7_start_call(struct sig_ss7_chan *p, struct sig_ss7_linkset *links
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 @@ static void ss7_start_call(struct sig_ss7_chan *p, struct sig_ss7_linkset *links
|
||||
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 @@ void *ss7_linkset(void *data)
|
||||
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 @@ void *ss7_linkset(void *data)
|
||||
}
|
||||
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 @@ void *ss7_linkset(void *data)
|
||||
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 @@ static inline void ss7_rel(struct sig_ss7_linkset *ss7)
|
||||
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 @@ static inline int ss7_grab(struct sig_ss7_chan *pvt, struct sig_ss7_linkset *ss7
|
||||
/* Then break the poll */
|
||||
if (ss7->master != AST_PTHREADT_NULL)
|
||||
pthread_kill(ss7->master, SIGURG);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -1302,10 +1319,7 @@ int sig_ss7_call(struct sig_ss7_chan *p, struct ast_channel *ast, char *rdest)
|
||||
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 @@ int sig_ss7_hangup(struct sig_ss7_chan *p, struct ast_channel *ast)
|
||||
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;
|
||||
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);
|
||||
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");
|
||||
}
|
||||
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 sig_ss7_answer(struct sig_ss7_chan *p, struct ast_channel *ast)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user