From: Jeff Peeler Date: Tue, 19 Jan 2010 17:22:18 +0000 (+0000) Subject: Fix deadlock in agent_read by removing call to agent_logoff. X-Git-Tag: 1.4.30-rc2~5^2~30 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=68e271504f5b2ecd174d41f4a72b6b3070424dae;p=thirdparty%2Fasterisk.git Fix deadlock in agent_read by removing call to agent_logoff. One must always lock the agents list lock before the agent private. agent_read locks the private immediately, so locking the agents list lock is not an option (which is what agent_logoff requires). Because agent_read already has access to the agent private all that is necessary is to do the required hanging up that agent_logoff performed. (closes issue #16321) Reported by: valon24 Patches: bug16321.patch uploaded by jpeeler (license 325) git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@241227 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- diff --git a/channels/chan_agent.c b/channels/chan_agent.c index c2b5b88dac..a8fca17244 100644 --- a/channels/chan_agent.c +++ b/channels/chan_agent.c @@ -550,7 +550,28 @@ static struct ast_frame *agent_read(struct ast_channel *ast) if (p->autologoff && (howlong >= p->autologoff)) { ast_log(LOG_NOTICE, "Agent '%s' didn't answer/confirm within %d seconds (waited %d)\n", p->name, p->autologoff, howlong); agent_logoff_maintenance(p, p->loginchan, (cur_time - p->loginstart), ast->uniqueid, "Autologoff"); - agent_logoff(p->agent, 0); + if (p->owner || p->chan) { + while (p->owner && ast_channel_trylock(p->owner)) { + DEADLOCK_AVOIDANCE(&p->lock); + } + if (p->owner) { + ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT); + ast_channel_unlock(p->owner); + } + + while (p->chan && ast_channel_trylock(p->chan)) { + DEADLOCK_AVOIDANCE(&p->lock); + } + if (p->chan) { + ast_softhangup(p->chan, AST_SOFTHANGUP_EXPLICIT); + ast_channel_unlock(p->chan); + } + } else { + long logintime; + logintime = time(NULL) - p->loginstart; + p->loginstart = 0; + agent_logoff_maintenance(p, p->loginchan, logintime, NULL, "CommandLogoff"); + } } } switch (f->frametype) {