diff -Naur asterisk-1.4.22.2/channels/chan_agent.c asterisk-1.4.22.2-patched/channels/chan_agent.c --- asterisk-1.4.22.2/channels/chan_agent.c 2008-09-05 23:10:32.000000000 +0200 +++ asterisk-1.4.22.2-patched/channels/chan_agent.c 2009-03-09 10:20:26.000000000 +0200 @@ -285,42 +285,55 @@ static int agent_devicestate_cb(const char *dev, int state, void *data) { - int res, i; - struct agent_pvt *p; - char basename[AST_CHANNEL_NAME], *tmp; + int res, i; + int stateUpdated = 0; + struct agent_pvt *p; + char basename[AST_CHANNEL_NAME], *tmp; + + /* Skip Agent status */ + if (!strncasecmp(dev, "Agent/", 6)) { + return 0; + } - /* Skip Agent status */ - if (!strncasecmp(dev, "Agent/", 6)) { - return 0; - } + /* SMR - We don't want to hold the lock on the agent list, so that at least if there is a deadlock calls will continue + * to be routed to agents + */ + while(!stateUpdated) { + /* Try to be safe, but don't deadlock */ + for (i = 0; i < 10; i++) { + if ((res = AST_LIST_TRYLOCK(&agents)) == 0) { + break; + } + } + if (res) { + return -1; + } + + AST_LIST_TRAVERSE(&agents, p, list) { + /* SMR - TRY and lock the agent, but don't block doing so */ + if (!ast_mutex_trylock(&p->lock)) { + if (p->chan) { + ast_copy_string(basename, p->chan->name, sizeof(basename)); + if ((tmp = strrchr(basename, '-'))) { + *tmp = '\0'; + } + if (strcasecmp(p->chan->name, dev) == 0 || strcasecmp(basename, dev) == 0) { + p->inherited_devicestate = state; + ast_device_state_changed("Agent/%s", p->agent); + stateUpdated = 1; + ast_log(LOG_DEBUG, "Agent/%s state updated to %d\n",p->agent,state); + } + } + ast_mutex_unlock(&p->lock); + } + } + AST_LIST_UNLOCK(&agents); + usleep(200); + } + return 0; +} - /* Try to be safe, but don't deadlock */ - for (i = 0; i < 10; i++) { - if ((res = AST_LIST_TRYLOCK(&agents)) == 0) { - break; - } - } - if (res) { - return -1; - } - AST_LIST_TRAVERSE(&agents, p, list) { - ast_mutex_lock(&p->lock); - if (p->chan) { - ast_copy_string(basename, p->chan->name, sizeof(basename)); - if ((tmp = strrchr(basename, '-'))) { - *tmp = '\0'; - } - if (strcasecmp(p->chan->name, dev) == 0 || strcasecmp(basename, dev) == 0) { - p->inherited_devicestate = state; - ast_device_state_changed("Agent/%s", p->agent); - } - } - ast_mutex_unlock(&p->lock); - } - AST_LIST_UNLOCK(&agents); - return 0; -} /*! * Adds an agent to the global list of agents. diff -Naur asterisk-1.4.22.2/channels/chan_local.c asterisk-1.4.22.2-patched/channels/chan_local.c --- asterisk-1.4.22.2/channels/chan_local.c 2008-06-27 14:19:39.000000000 +0200 +++ asterisk-1.4.22.2-patched/channels/chan_local.c 2009-03-09 10:16:52.000000000 +0200 @@ -511,12 +511,11 @@ if (!p) return -1; + /* SMR - Use the macro rather */ + while (ast_mutex_trylock(&p->lock)) { + DEADLOCK_AVOIDANCE(&ast->lock); + } - while (ast_mutex_trylock(&p->lock)) { - ast_channel_unlock(ast); - usleep(1); - ast_channel_lock(ast); - } isoutbound = IS_OUTBOUND(ast, p); if (isoutbound) {