mirror of
https://github.com/asterisk/asterisk.git
synced 2025-11-09 11:28:25 +00:00
Fix potential deadlock calling ast_call() with channel locks held.
Fixed app_queue.c:ring_entry() calling ast_call() with the channel locks held. Chan_local attempts to do deadlock avoidance in its ast_call() callback and could deadlock if a channel lock is already held. git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.8@344539 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -3058,10 +3058,7 @@ static int ring_entry(struct queue_ent *qe, struct callattempt *tmp, int *busies
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ast_channel_lock(tmp->chan);
|
ast_channel_lock_both(tmp->chan, qe->chan);
|
||||||
while (ast_channel_trylock(qe->chan)) {
|
|
||||||
CHANNEL_DEADLOCK_AVOIDANCE(tmp->chan);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (qe->cancel_answered_elsewhere) {
|
if (qe->cancel_answered_elsewhere) {
|
||||||
ast_set_flag(tmp->chan, AST_FLAG_ANSWERED_ELSEWHERE);
|
ast_set_flag(tmp->chan, AST_FLAG_ANSWERED_ELSEWHERE);
|
||||||
@@ -3124,13 +3121,14 @@ static int ring_entry(struct queue_ent *qe, struct callattempt *tmp, int *busies
|
|||||||
strcpy(tmp->chan->cdr->userfield, qe->chan->cdr->userfield);
|
strcpy(tmp->chan->cdr->userfield, qe->chan->cdr->userfield);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ast_channel_unlock(tmp->chan);
|
||||||
|
ast_channel_unlock(qe->chan);
|
||||||
|
|
||||||
/* Place the call, but don't wait on the answer */
|
/* Place the call, but don't wait on the answer */
|
||||||
if ((res = ast_call(tmp->chan, location, 0))) {
|
if ((res = ast_call(tmp->chan, location, 0))) {
|
||||||
/* Again, keep going even if there's an error */
|
/* Again, keep going even if there's an error */
|
||||||
ast_debug(1, "ast call on peer returned %d\n", res);
|
ast_debug(1, "ast call on peer returned %d\n", res);
|
||||||
ast_verb(3, "Couldn't call %s\n", tmp->interface);
|
ast_verb(3, "Couldn't call %s\n", tmp->interface);
|
||||||
ast_channel_unlock(tmp->chan);
|
|
||||||
ast_channel_unlock(qe->chan);
|
|
||||||
do_hang(tmp);
|
do_hang(tmp);
|
||||||
(*busies)++;
|
(*busies)++;
|
||||||
update_status(qe->parent, tmp->member, get_queue_member_status(tmp->member));
|
update_status(qe->parent, tmp->member, get_queue_member_status(tmp->member));
|
||||||
@@ -3138,6 +3136,8 @@ static int ring_entry(struct queue_ent *qe, struct callattempt *tmp, int *busies
|
|||||||
} else if (qe->parent->eventwhencalled) {
|
} else if (qe->parent->eventwhencalled) {
|
||||||
char vars[2048];
|
char vars[2048];
|
||||||
|
|
||||||
|
ast_channel_lock_both(tmp->chan, qe->chan);
|
||||||
|
|
||||||
manager_event(EVENT_FLAG_AGENT, "AgentCalled",
|
manager_event(EVENT_FLAG_AGENT, "AgentCalled",
|
||||||
"Queue: %s\r\n"
|
"Queue: %s\r\n"
|
||||||
"AgentCalled: %s\r\n"
|
"AgentCalled: %s\r\n"
|
||||||
@@ -3160,11 +3160,13 @@ static int ring_entry(struct queue_ent *qe, struct callattempt *tmp, int *busies
|
|||||||
S_COR(qe->chan->connected.id.name.valid, qe->chan->connected.id.name.str, "unknown"),
|
S_COR(qe->chan->connected.id.name.valid, qe->chan->connected.id.name.str, "unknown"),
|
||||||
qe->chan->context, qe->chan->exten, qe->chan->priority, qe->chan->uniqueid,
|
qe->chan->context, qe->chan->exten, qe->chan->priority, qe->chan->uniqueid,
|
||||||
qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
|
qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
|
||||||
ast_verb(3, "Called %s\n", tmp->interface);
|
|
||||||
}
|
|
||||||
ast_channel_unlock(tmp->chan);
|
ast_channel_unlock(tmp->chan);
|
||||||
ast_channel_unlock(qe->chan);
|
ast_channel_unlock(qe->chan);
|
||||||
|
|
||||||
|
ast_verb(3, "Called %s\n", tmp->interface);
|
||||||
|
}
|
||||||
|
|
||||||
update_status(qe->parent, tmp->member, get_queue_member_status(tmp->member));
|
update_status(qe->parent, tmp->member, get_queue_member_status(tmp->member));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -3583,10 +3585,7 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte
|
|||||||
} else {
|
} else {
|
||||||
struct ast_party_redirecting redirecting;
|
struct ast_party_redirecting redirecting;
|
||||||
|
|
||||||
ast_channel_lock(o->chan);
|
ast_channel_lock_both(o->chan, in);
|
||||||
while (ast_channel_trylock(in)) {
|
|
||||||
CHANNEL_DEADLOCK_AVOIDANCE(o->chan);
|
|
||||||
}
|
|
||||||
ast_channel_inherit_variables(in, o->chan);
|
ast_channel_inherit_variables(in, o->chan);
|
||||||
ast_channel_datastore_inherit(in, o->chan);
|
ast_channel_datastore_inherit(in, o->chan);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user