Index: apps/app_queue.c =================================================================== --- apps/app_queue.c (revision 79208) +++ apps/app_queue.c (working copy) @@ -313,6 +313,7 @@ }; struct member { + ast_mutex_t member_lock; char interface[80]; /*!< Technology/Location */ char membername[80]; /*!< Member name to use in queue logs */ int penalty; /*!< Are we a last resort? */ @@ -623,6 +624,7 @@ struct member *cur; if ((cur = ast_calloc(1, sizeof(*cur)))) { + ast_mutex_init(&cur->member_lock); cur->penalty = penalty; cur->paused = paused; ast_copy_string(cur->interface, interface, sizeof(cur->interface)); @@ -977,16 +979,24 @@ for (curm = q->members; curm; curm = next) { next = curm->next; + ast_mutex_lock(&curm->member_lock); if (all || !curm->dynamic) { if (prev) prev->next = next; else q->members = next; remove_from_interfaces(curm->interface); + ast_mutex_unlock(&curm->member_lock); + usleep(1); + ast_mutex_lock(&curm->member_lock); + ast_mutex_unlock(&curm->member_lock); + ast_mutex_destroy(&curm->member_lock); q->membercount--; free(curm); - } else + } else { + ast_mutex_unlock(&curm->member_lock); prev = curm; + } } } @@ -1099,6 +1109,7 @@ m = q->members; prev_m = NULL; while (m) { + ast_mutex_lock(&m->member_lock); next_m = m->next; if (m->dead) { if (prev_m) { @@ -1107,10 +1118,16 @@ q->members = next_m; } remove_from_interfaces(m->interface); + ast_mutex_unlock(&m->member_lock); + usleep(1); + ast_mutex_lock(&m->member_lock); + ast_mutex_unlock(&m->member_lock); + ast_mutex_destroy(&m->member_lock); q->membercount--; free(m); } else { prev_m = m; + ast_mutex_unlock(&m->member_lock); } m = next_m; } @@ -2135,7 +2152,8 @@ if (!*to) rna(orig, qe, on, membername); } - + if(peer) + ast_mutex_lock(&peer->member->member_lock); return peer; } @@ -2353,7 +2371,7 @@ struct ast_channel *peer; struct ast_channel *which; struct callattempt *lpeer; - struct member *member; + struct member *member = NULL; struct ast_app *app; int res = 0, bridge = 0; int numbusies = 0; @@ -2555,6 +2573,7 @@ ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "ABANDON", "%d|%d|%ld", qe->pos, qe->opos, (long)time(NULL) - qe->start); record_abandoned(qe); ast_hangup(peer); + ast_mutex_unlock(&member->member_lock); return -1; } } @@ -2570,6 +2589,7 @@ ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", qe->chan->name, peer->name); record_abandoned(qe); ast_hangup(peer); + ast_mutex_unlock(&member->member_lock); return -1; } /* Begin Monitoring */ @@ -2751,7 +2771,8 @@ } out: hangupcalls(outgoing, NULL); - + if(member) + ast_mutex_unlock(&member->member_lock); return res; } @@ -2767,6 +2788,7 @@ return res; } +/*! interface_exists now returns a locked structure */ static struct member *interface_exists(struct call_queue *q, const char *interface) { struct member *mem; @@ -2775,8 +2797,10 @@ return NULL; for (mem = q->members; mem; mem = mem->next) { + ast_mutex_lock(&mem->member_lock); if (!strcasecmp(interface, mem->interface)) return mem; + ast_mutex_unlock(&mem->member_lock); } return NULL; @@ -2844,7 +2868,6 @@ while (look != NULL) { if (look->next == last_member) { look->next = last_member->next; - q->membercount--; break; } else { look = look->next; @@ -2856,6 +2879,11 @@ "Location: %s\r\n" "MemberName: %s\r\n", q->name, last_member->interface, last_member->membername); + ast_mutex_unlock(&last_member->member_lock); + usleep(1); + ast_mutex_lock(&last_member->member_lock); + ast_mutex_unlock(&last_member->member_lock); + ast_mutex_destroy(&last_member->member_lock); free(last_member); if (queue_persistent_members) @@ -2892,7 +2920,7 @@ AST_LIST_LOCK(&queues); ast_mutex_lock(&q->lock); - if (interface_exists(q, interface) == NULL) { + if ((new_member = interface_exists(q, interface)) == NULL) { add_to_interfaces(interface); if ((new_member = create_queue_member(interface, membername, penalty, paused))) { new_member->dynamic = 1; @@ -2922,6 +2950,7 @@ res = RES_OUTOFMEMORY; } } else { + ast_mutex_unlock(&new_member->member_lock); res = RES_EXISTS; } ast_mutex_unlock(&q->lock); @@ -2962,6 +2991,7 @@ "MemberName: %s\r\n" "Paused: %d\r\n", q->name, mem->interface, mem->membername, paused); + ast_mutex_unlock(&mem->member_lock); } } ast_mutex_unlock(&q->lock); @@ -3862,6 +3892,7 @@ newm = create_queue_member(interface, membername, penalty, cur ? cur->paused : 0); if (cur) { + ast_mutex_lock(&cur->member_lock); /* Delete it now */ newm->next = cur->next; if (prev) { @@ -3869,6 +3900,11 @@ } else { q->members = newm; } + ast_mutex_unlock(&cur->member_lock); + usleep(1); + ast_mutex_lock(&cur->member_lock); + ast_mutex_unlock(&cur->member_lock); + ast_mutex_destroy(&cur->member_lock); free(cur); } else { /* Add them to the master int list if necessary */ @@ -3886,6 +3922,7 @@ for (prev = NULL, cur = q->members; cur; cur = next) { + ast_mutex_lock(&cur->member_lock); next = cur->next; if (!cur->delme) { @@ -3900,6 +3937,11 @@ remove_from_interfaces(cur->interface); q->membercount--; + ast_mutex_unlock(&cur->member_lock); + usleep(1); + ast_mutex_lock(&cur->member_lock); + ast_mutex_unlock(&cur->member_lock); + ast_mutex_destroy(&cur->member_lock); free(cur); }