aboutsummaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
authormarkster <markster@f38db490-d61c-443f-a65b-d21fe96a405b>2005-03-19 17:35:59 +0000
committermarkster <markster@f38db490-d61c-443f-a65b-d21fe96a405b>2005-03-19 17:35:59 +0000
commit8dc4ba23e4628a27fb7959095e92f8b27274c907 (patch)
tree6c417ef880b14b0b34300d0efa3905e225d331a8 /apps
parente941a126ad0e84ce4e11fccd3eb06fa9dacf53ee (diff)
Fix queue stuff (bug #3797)
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@5205 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'apps')
-rwxr-xr-xapps/app_queue.c57
1 files changed, 26 insertions, 31 deletions
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, '/')))