diff options
author | Mark Spencer <markster@digium.com> | 2003-07-01 03:32:14 +0000 |
---|---|---|
committer | Mark Spencer <markster@digium.com> | 2003-07-01 03:32:14 +0000 |
commit | cbe865df7a4aba9df5e5bb3b3568fb64ede27013 (patch) | |
tree | 5a4486d042e79ea64f1adef1885002a231d99833 | |
parent | e78cef0d9fb259fc78a23b27658ccf787f8f1e02 (diff) |
Fix race in local, update queue
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@1143 65c4cc65-6c06-0410-ace0-fbb531ad65f3
-rwxr-xr-x | apps/app_queue.c | 42 | ||||
-rwxr-xr-x | channels/chan_local.c | 25 |
2 files changed, 64 insertions, 3 deletions
diff --git a/apps/app_queue.c b/apps/app_queue.c index a51338542..d6a823bfd 100755 --- a/apps/app_queue.c +++ b/apps/app_queue.c @@ -1156,6 +1156,46 @@ static int manager_queues_show( struct mansession *s, struct message *m ) return queues_show( s->fd, 2, a ); } /* /JDG */ + +/* Dump queue status */ +static int manager_queues_status( struct mansession *s, struct message *m ) +{ + time_t now; + int pos; + struct ast_call_queue *q; + struct queue_ent *qe; + astman_send_ack(s, "Queue status will follow"); + time(&now); + q = queues; + while(q) { + ast_pthread_mutex_lock(&q->lock); + ast_cli(s->fd, "Event: QueueParams\r\n" + "Queue: %s\r\n" + "Max: %d\r\n" + "Calls: %d\r\n" + "\r\n", + q->name, q->maxlen, q->count); +#if 0 + /* Do we care about queue members? */ + for (mem = q->members; mem; mem = mem->next) + ast_cli(fd, " %s/%s\n", mem->tech, mem->loc); +#endif + pos = 1; + for (qe = q->head; qe; qe = qe->next) + ast_cli(s->fd, "Event: QueueMember\r\n" + "Queue: %s\r\n" + "Position: %d\r\n" + "Channel: %s\r\n" + "CallerID: %s\r\n" + "Wait: %ld\r\n" + "\r\n", + q->name, pos++, qe->chan->name, qe->chan->callerid ? qe->chan->callerid : "", now - qe->start); + ast_pthread_mutex_unlock(&q->lock); + q = q->next; + } + return RESULT_SUCCESS; +} + static char show_queues_usage[] = "Usage: show queues\n" " Provides summary information on call queues.\n"; @@ -1169,6 +1209,7 @@ int unload_module(void) STANDARD_HANGUP_LOCALUSERS; ast_cli_unregister(&cli_show_queues); ast_manager_unregister( "Queues" ); + ast_manager_unregister( "QueueStatus" ); return ast_unregister_application(app); } @@ -1179,6 +1220,7 @@ int load_module(void) if (!res) { ast_cli_register(&cli_show_queues); ast_manager_register( "Queues", 0, manager_queues_show, "Queues" ); + ast_manager_register( "QueueStatus", 0, manager_queues_status, "Queue Status" ); // [PHM 06/26/03] ast_register_application(app_aqm, aqm_exec, app_aqm_synopsis, app_aqm_descrip) ; diff --git a/channels/chan_local.c b/channels/chan_local.c index 4c4d4e1de..7567c81e4 100755 --- a/channels/chan_local.c +++ b/channels/chan_local.c @@ -61,6 +61,8 @@ static struct local_pvt { char context[AST_MAX_EXTENSION]; /* Context to call */ char exten[AST_MAX_EXTENSION]; /* Extension to call */ int reqformat; /* Requested format */ + int glaredetect; /* Detect glare on hangup */ + int cancelqueue; /* Cancel queue */ int alreadymasqed; /* Already masqueraded */ struct ast_channel *owner; /* Master Channel */ struct ast_channel *chan; /* Outbound channel */ @@ -76,7 +78,15 @@ static int local_queue_frame(struct local_pvt *p, int isoutbound, struct ast_fra other = p->chan; if (!other) return 0; + p->glaredetect = 1; retrylock: + if (p->cancelqueue) { + /* We had a glare on the hangup. Forget all this business, + return and destroy p. */ + ast_pthread_mutex_unlock(&p->lock); + free(p); + return -1; + } if (pthread_mutex_trylock(&other->lock)) { /* Failed to lock. Release main lock and try again */ ast_pthread_mutex_unlock(&p->lock); @@ -87,6 +97,7 @@ retrylock: } ast_queue_frame(other, f, 0); ast_pthread_mutex_unlock(&other->lock); + p->glaredetect = 0; return 0; } @@ -231,6 +242,7 @@ static int local_hangup(struct ast_channel *ast) struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_HANGUP }; struct local_pvt *cur, *prev=NULL; struct ast_channel *ochan = NULL; + int glaredetect; ast_pthread_mutex_lock(&p->lock); if (isoutbound) p->chan = NULL; @@ -240,6 +252,11 @@ static int local_hangup(struct ast_channel *ast) if (!p->owner && !p->chan) { /* Okay, done with the private part now, too. */ + glaredetect = p->glaredetect; + /* If we have a queue holding, don't actually destroy p yet, but + let local_queue do it. */ + if (p->glaredetect) + p->cancelqueue = 1; ast_pthread_mutex_unlock(&p->lock); /* Remove from list */ ast_pthread_mutex_lock(&locallock); @@ -257,7 +274,8 @@ static int local_hangup(struct ast_channel *ast) } ast_pthread_mutex_unlock(&locallock); /* And destroy */ - free(p); + if (!glaredetect) + free(p); return 0; } if (p->chan && !p->chan->pbx) @@ -307,6 +325,7 @@ static struct local_pvt *local_alloc(char *data, int format) static struct ast_channel *local_new(struct local_pvt *p, int state) { struct ast_channel *tmp, *tmp2; + int randnum = rand() & 0xffff; tmp = ast_channel_alloc(1); tmp2 = ast_channel_alloc(1); if (!tmp || !tmp2) { @@ -319,8 +338,8 @@ static struct ast_channel *local_new(struct local_pvt *p, int state) if (tmp) { tmp->nativeformats = p->reqformat; tmp2->nativeformats = p->reqformat; - snprintf(tmp->name, sizeof(tmp->name), "Local/%s@%s-1", p->exten, p->context); - snprintf(tmp2->name, sizeof(tmp2->name), "Local/%s@%s-2", p->exten, p->context); + snprintf(tmp->name, sizeof(tmp->name), "Local/%s@%s-%04x.1", p->exten, p->context, randnum); + snprintf(tmp2->name, sizeof(tmp2->name), "Local/%s@%s-%04x,2", p->exten, p->context, randnum); tmp->type = type; tmp2->type = type; ast_setstate(tmp, state); |