From 8dc4ba23e4628a27fb7959095e92f8b27274c907 Mon Sep 17 00:00:00 2001 From: markster Date: Sat, 19 Mar 2005 17:35:59 +0000 Subject: Fix queue stuff (bug #3797) git-svn-id: http://svn.digium.com/svn/asterisk/trunk@5205 f38db490-d61c-443f-a65b-d21fe96a405b --- apps/app_queue.c | 57 ++++++++++++++++++++++++++------------------------------ 1 file changed, 26 insertions(+), 31 deletions(-) (limited to 'apps') diff --git a/apps/app_queue.c b/apps/app_queue.c index 60c5b2a0e..e89930356 100755 --- a/apps/app_queue.c +++ b/apps/app_queue.c @@ -746,35 +746,33 @@ static int update_dial_status(struct ast_call_queue *q, struct member *member, i return update_status(q, member, status); } -static int compare_weight(struct ast_call_queue *req_q, struct localuser *req_user, char *qname) +static int compare_weight(struct ast_call_queue *rq, struct member *member) { /* traverse all defined queues which have calls waiting and contain this member return 0 if no other queue has precedence (higher weight) or 1 if found */ struct ast_call_queue *q; struct member *mem; - int found = 0, weight = 0, calls = 0; - char name[80] = ""; - - strncpy(name, req_q->name, sizeof(name) - 1); - weight = req_q->weight; - calls = req_q->count; + int found = 0; + /* avoid deadlock which can occur under specific condition. + * another queue-walking func may be waiting for rq->lock, which + * was set by try_calling, but won't unlock til this finishes, + * yet we're waiting for &qlock. happy fun times! */ + ast_mutex_unlock(&rq->lock); ast_mutex_lock(&qlock); - for (q = queues; q; q = q->next) { /* spin queues */ - ast_mutex_lock(&q->lock); - if (!strcasecmp(q->name, name)) { /* don't check myself */ - ast_mutex_unlock(&q->lock); + ast_mutex_lock(&rq->lock); + for (q = queues; q; q = q->next) { + if (q == rq) /* don't check myself */ continue; - } - if (q->count && q->members) { /* check only if calls waiting and has members */ - for (mem = q->members; mem; mem = mem->next) { /* spin members */ - if (!strcasecmp(mem->interface, req_user->interface)) { + ast_mutex_lock(&q->lock); + if (q->count && q->members) { + for (mem = q->members; mem; mem = mem->next) { + if (mem == member) { ast_log(LOG_DEBUG, "Found matching member %s in queue '%s'\n", mem->interface, q->name); - if (q->weight > weight) { - ast_log(LOG_DEBUG, "Queue '%s' (weight %d, calls %d) is preferred over '%s' (weight %d, calls %d)\n", q->name, q->weight, q->count, name, weight, calls); + if (q->weight > rq->weight) { + ast_log(LOG_DEBUG, "Queue '%s' (weight %d, calls %d) is preferred over '%s' (weight %d, calls %d)\n", q->name, q->weight, q->count, rq->name, rq->weight, rq->count); found = 1; - strncpy(qname, q->name, sizeof(qname) - 1); - break; /* stop looking for more members */ + break; } } } @@ -795,18 +793,7 @@ static int ring_entry(struct queue_ent *qe, struct localuser *tmp, int *busies) int status; char tech[256]; char *location; - char qname[80] = ""; - - if (use_weight) { /* fast path */ - if (compare_weight(qe->parent,tmp,qname)) { - ast_verbose(VERBOSE_PREFIX_3 "Attempt (%s: %s) delayed by higher priority queue (%s).\n", qe->parent->name, tmp->interface, qname); - if (qe->chan->cdr) - ast_cdr_busy(qe->chan->cdr); - tmp->stillgoing = 0; - (*busies)++; - return 0; - } - } + if (qe->parent->wrapuptime && (time(NULL) - tmp->lastcall < qe->parent->wrapuptime)) { if (option_debug) ast_log(LOG_DEBUG, "Wrapuptime not yet expired for %s\n", tmp->interface); @@ -825,6 +812,14 @@ static int ring_entry(struct queue_ent *qe, struct localuser *tmp, int *busies) tmp->stillgoing = 0; return 0; } + if (use_weight && compare_weight(qe->parent,tmp->member)) { + ast_log(LOG_DEBUG, "Priority queue delaying call to %s:%s\n", qe->parent->name, tmp->interface); + if (qe->chan->cdr) + ast_cdr_busy(qe->chan->cdr); + tmp->stillgoing = 0; + (*busies)++; + return 0; + } strncpy(tech, tmp->interface, sizeof(tech) - 1); if ((location = strchr(tech, '/'))) -- cgit v1.2.3