Index: main/pbx.c =================================================================== --- main/pbx.c (revision 314992) +++ main/pbx.c (working copy) @@ -3121,7 +3121,18 @@ .destroy = exception_store_free, }; -int pbx_builtin_raise_exception(struct ast_channel *chan, const char *reason) +/*! + * \internal + * \brief Set the PBX to execute the exception extension. + * + * \param chan Channel to raise the exception on. + * \param reason Reason exception is raised. + * \param priority Dialplan priority to set. + * + * \retval 0 on success. + * \retval -1 on error. + */ +static int raise_exception(struct ast_channel *chan, const char *reason, int priority) { struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL); struct pbx_exception *exception = NULL; @@ -3143,10 +3154,16 @@ ast_string_field_set(exception, context, chan->context); ast_string_field_set(exception, exten, chan->exten); exception->priority = chan->priority; - set_ext_pri(chan, "e", 0); + set_ext_pri(chan, "e", priority); return 0; } +int pbx_builtin_raise_exception(struct ast_channel *chan, const char *reason) +{ + /* Priority will become 1, next time through the AUTOLOOP */ + return raise_exception(chan, reason, 0); +} + static int acf_exception_read(struct ast_channel *chan, const char *name, char *data, char *buf, size_t buflen) { struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL); @@ -4716,7 +4733,7 @@ } else if ((c->_softhangup & AST_SOFTHANGUP_TIMEOUT) && ast_exists_extension(c, c->context, "e", 1, S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { - pbx_builtin_raise_exception(c, "ABSOLUTETIMEOUT"); + raise_exception(c, "ABSOLUTETIMEOUT", 0); /* 0 will become 1 with the c->priority++; at the end */ /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ memset(&c->whentohangup, 0, sizeof(c->whentohangup)); ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT); @@ -4763,7 +4780,7 @@ ast_verb(2, "Spawn extension (%s, %s, %d) exited ERROR while already on 'e' exten on '%s'\n", c->context, c->exten, c->priority, c->name); error = 1; } else { - pbx_builtin_raise_exception(c, "ERROR"); + raise_exception(c, "ERROR", 1); continue; } } @@ -4779,6 +4796,14 @@ memset(&c->whentohangup, 0, sizeof(c->whentohangup)); ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT); continue; + } else if ((c->_softhangup & AST_SOFTHANGUP_TIMEOUT) + && ast_exists_extension(c, c->context, "e", 1, + S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { + raise_exception(c, "ABSOLUTETIMEOUT", 1); + /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */ + memset(&c->whentohangup, 0, sizeof(c->whentohangup)); + ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT); + continue; } else { if (c->cdr) ast_cdr_update(c); @@ -4810,7 +4835,7 @@ set_ext_pri(c, "i", 1); } else if (ast_exists_extension(c, c->context, "e", 1, S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { - pbx_builtin_raise_exception(c, "INVALID"); + raise_exception(c, "INVALID", 1); } else { ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n", c->name, c->exten, c->context); @@ -4860,9 +4885,11 @@ set_ext_pri(c, "i", 1); } else if (ast_exists_extension(c, c->context, "e", 1, S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { - pbx_builtin_raise_exception(c, "INVALID"); + raise_exception(c, "INVALID", 1); } else { - ast_log(LOG_WARNING, "Invalid extension '%s', but no rule 'i' in context '%s'\n", dst_exten, c->context); + ast_log(LOG_WARNING, + "Invalid extension '%s', but no rule 'i' or 'e' in context '%s'\n", + dst_exten, c->context); found = 1; /* XXX disable message */ break; } @@ -4874,9 +4901,11 @@ set_ext_pri(c, "t", 1); } else if (ast_exists_extension(c, c->context, "e", 1, S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { - pbx_builtin_raise_exception(c, "RESPONSETIMEOUT"); + raise_exception(c, "RESPONSETIMEOUT", 1); } else { - ast_log(LOG_WARNING, "Timeout, but no rule 't' in context '%s'\n", c->context); + ast_log(LOG_WARNING, + "Timeout, but no rule 't' or 'e' in context '%s'\n", + c->context); found = 1; /* XXX disable message */ break; } @@ -9284,8 +9313,12 @@ S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) { ast_verb(3, "Timeout on %s, going to 't'\n", chan->name); set_ext_pri(chan, "t", 0); /* 0 will become 1, next time through the loop */ + } else if (ast_exists_extension(chan, chan->context, "e", 1, + S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) { + raise_exception(chan, "RESPONSETIMEOUT", 0); /* 0 will become 1, next time through the loop */ } else { - ast_log(LOG_WARNING, "Timeout but no rule 't' in context '%s'\n", chan->context); + ast_log(LOG_WARNING, "Timeout but no rule 't' or 'e' in context '%s'\n", + chan->context); res = -1; } }