aboutsummaryrefslogtreecommitdiffstats
path: root/channels/chan_dahdi.c
diff options
context:
space:
mode:
authormmichelson <mmichelson@f38db490-d61c-443f-a65b-d21fe96a405b>2008-12-22 21:55:59 +0000
committermmichelson <mmichelson@f38db490-d61c-443f-a65b-d21fe96a405b>2008-12-22 21:55:59 +0000
commit3fa01978b52c71b970120b96bfb3b33317f77e90 (patch)
treef8b0e0e10815e9a20dafe161f64c6bf8a7e3920a /channels/chan_dahdi.c
parent50892e7af951b4e48b565c56beeee547e1904a31 (diff)
Merged revisions 166382 via svnmerge from
https://origsvn.digium.com/svn/asterisk/trunk ................ r166382 | mmichelson | 2008-12-22 15:08:03 -0600 (Mon, 22 Dec 2008) | 44 lines Merged revisions 166380 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r166380 | mmichelson | 2008-12-22 14:56:29 -0600 (Mon, 22 Dec 2008) | 36 lines Fix a deadlock relating to channel locks and autoservice It has been discovered that if a channel is locked prior to a call to ast_autoservice_stop, then it is likely that a deadlock will occur. The reason is that the call to ast_autoservice_stop has a check built into it to be sure that the thread running autoservice is not currently trying to manipulate the channel we are about to pull out of autoservice. The autoservice thread, however, cannot advance beyond where it currently is, though, because it is trying to acquire the lock of the channel for which autoservice is attempting to be stopped. The gist of all this is that a channel MUST NOT be locked when attempting to stop autoservice on the channel. In this particular case, the channel was locked by a call to ast_read. A call to ast_exists_extension led to autoservice being started and stopped due to the existence of dialplan switches. It may be that there are future commits which handle the same symptoms but in a different location, but based on my looks through the code, it is very rare to see a construct such as this one. (closes issue #14057) Reported by: rtrauntvein Patches: 14057v3.patch uploaded by putnopvut (license 60) Tested by: rtrauntvein Review: http://reviewboard.digium.com/r/107/ ........ ................ git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.6.0@166439 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channels/chan_dahdi.c')
-rw-r--r--channels/chan_dahdi.c19
1 files changed, 16 insertions, 3 deletions
diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c
index c13ba4431..75dda32ca 100644
--- a/channels/chan_dahdi.c
+++ b/channels/chan_dahdi.c
@@ -4262,18 +4262,31 @@ static void dahdi_handle_dtmfup(struct ast_channel *ast, int index, struct ast_f
if (strcmp(ast->exten, "fax")) {
const char *target_context = S_OR(ast->macrocontext, ast->context);
+ /* We need to unlock 'ast' here because ast_exists_extension has the
+ * potential to start autoservice on the channel. Such action is prone
+ * to deadlock.
+ */
+ ast_mutex_unlock(&p->lock);
+ ast_channel_unlock(ast);
if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
+ ast_channel_lock(ast);
+ ast_mutex_lock(&p->lock);
ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
/* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
if (ast_async_goto(ast, target_context, "fax", 1))
ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
- } else
+ } else {
+ ast_channel_lock(ast);
+ ast_mutex_lock(&p->lock);
ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
- } else
+ }
+ } else {
ast_debug(1, "Already in a fax extension, not redirecting\n");
- } else
+ }
+ } else {
ast_debug(1, "Fax already handled\n");
+ }
dahdi_confmute(p, 0);
p->subs[index].f.frametype = AST_FRAME_NULL;
p->subs[index].f.subclass = 0;