Index: apps/app_queue.c =================================================================== --- apps/app_queue.c (revision 85551) +++ apps/app_queue.c (working copy) @@ -524,14 +524,40 @@ } struct statechange { + AST_LIST_ENTRY(statechange) list; int state; char dev[0]; }; -static void *changethread(void *data) +static AST_LIST_HEAD_STATIC(device_state_changes, statechange); +static pthread_t change_thread = AST_PTHREADT_NULL; +static ast_cond_t device_change_pending; +static void *do_device_change(const struct statechange *sc); + +static void *changethread(void *unused) { + struct statechange *sc = NULL; + + AST_LIST_LOCK(&device_state_changes); + for (;;) { + sc = AST_LIST_REMOVE_HEAD(&device_state_changes, list); + if (sc) { + AST_LIST_UNLOCK(&device_state_changes); + do_device_change(sc); + free(sc); + AST_LIST_LOCK(&device_state_changes); + } else { + ast_cond_wait(&device_change_pending, &device_state_changes.lock); + } + } + + return NULL; +} + + +static void *do_device_change(const struct statechange *sc) +{ struct call_queue *q; - struct statechange *sc = data; struct member *cur; struct ao2_iterator mem_iter; struct member_interface *curint; @@ -543,7 +569,6 @@ if (loc) { *loc++ = '\0'; } else { - free(sc); return NULL; } @@ -564,7 +589,6 @@ if (!curint) { if (option_debug > 2) ast_log(LOG_DEBUG, "Device '%s/%s' changed to state '%d' (%s) but we don't care because they're not a member of any queue.\n", technology, loc, sc->state, devstate2str(sc->state)); - free(sc); return NULL; } @@ -613,7 +637,7 @@ } AST_LIST_UNLOCK(&queues); - free(sc); + free((struct statechange *)sc); return NULL; } @@ -623,22 +647,18 @@ /* Avoid potential for deadlocks by spawning a new thread to handle the event */ struct statechange *sc; - pthread_t t; - pthread_attr_t attr; - if (!(sc = ast_calloc(1, sizeof(*sc) + strlen(dev) + 1))) + if (!(sc = calloc(1, sizeof(*sc) + strlen(dev) + 1))) return 0; sc->state = state; strcpy(sc->dev, dev); - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - if (ast_pthread_create_background(&t, &attr, changethread, sc)) { - ast_log(LOG_WARNING, "Failed to create update thread!\n"); - free(sc); - } - pthread_attr_destroy(&attr); + AST_LIST_LOCK(&device_state_changes); + AST_LIST_INSERT_TAIL(&device_state_changes, sc, list); + ast_cond_signal(&device_change_pending); + AST_LIST_UNLOCK(&device_state_changes); + return 0; } @@ -1269,7 +1289,7 @@ if (!member_config) { ast_log(LOG_ERROR, "no queue_members defined in your config (extconfig.conf).\n"); return NULL; - } + } } AST_LIST_LOCK(&queues); @@ -4633,6 +4653,12 @@ return AST_MODULE_LOAD_DECLINE; if (queue_persistent_members) reload_queue_members(); + + if (change_thread == AST_PTHREADT_NULL) { + ast_cond_init(&device_change_pending, NULL); + ast_pthread_create(&change_thread, NULL, changethread, NULL); + } + ast_cli_register_multiple(cli_queue, sizeof(cli_queue) / sizeof(struct ast_cli_entry)); res = ast_register_application(app, queue_exec, synopsis, descrip); res |= ast_register_application(app_aqm, aqm_exec, app_aqm_synopsis, app_aqm_descrip);