Index: main/features.c =================================================================== --- main/features.c (revision 243115) +++ main/features.c (working copy) @@ -3052,9 +3052,9 @@ struct ast_cdr *swapper = NULL; char savelastapp[AST_MAX_EXTENSION]; char savelastdata[AST_MAX_EXTENSION]; - char save_exten[AST_MAX_EXTENSION]; + char save_context[AST_MAX_CONTEXT], save_exten[AST_MAX_EXTENSION]; int save_prio; - int found = 0; /* set if we find at least one match */ + int found = 0, was_found = 0; /* set if we find at least one match */ int spawn_error = 0; autoloopflag = ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP); @@ -3071,25 +3071,43 @@ ast_copy_string(savelastdata, bridge_cdr->lastdata, sizeof(bridge_cdr->lastdata)); chan->cdr = bridge_cdr; } + ast_copy_string(save_context, chan->context, sizeof(save_context)); ast_copy_string(save_exten, chan->exten, sizeof(save_exten)); save_prio = chan->priority; ast_copy_string(chan->exten, "h", sizeof(chan->exten)); chan->priority = 1; ast_channel_unlock(chan); - while ((spawn_error = ast_spawn_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num, &found, 1)) == 0) { + while ((spawn_error = ast_spawn_extension(chan, S_OR(chan->macrocontext, chan->context), chan->exten, chan->priority, chan->cid.cid_num, &found, 1)) == 0) { + if (found) { + /* Why save? Because if the "h" extension exits with a Goto to + * a non-existent location, it DID execute, but found will end + * up being 0. */ + was_found++; + } chan->priority++; } - if (spawn_error && (!ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num) || ast_check_hangup(chan))) { - /* if the extension doesn't exist or a hangup occurred, this isn't really a spawn error */ + if (was_found || spawn_error == -ENOSYS) { + /* If at least one priority executed, or the application doesn't + * exist, this isn't really a spawn error. Hangup is irrelevant, + * because we're in the "h" extension -- of course a hangup + * occurred, or we wouldn't be here in the first place. If I'm + * wrong, and we did want to detect hangup, we'd need to be + * selective about which hangup causes we would want to detect -- + * an ASYNCGOTO, for example, would not be one of them, nor would + * an (absolute) TIMEOUT, nor an UNBRIDGE. So ast_check_hangup() + * would be useless for this purpose. In fact, if any of those + * happened, we probably wouldn't want to be executing the "h" + * extension in the first place. */ spawn_error = 0; } - if (found && spawn_error) { + if (was_found && spawn_error) { /* Something bad happened, or a hangup has been requested. */ ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", chan->context, chan->exten, chan->priority, chan->name); ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", chan->context, chan->exten, chan->priority, chan->name); } - /* swap it back */ + /* swap original context/extension/priority back */ ast_channel_lock(chan); + ast_copy_string(chan->context, save_context, sizeof(chan->context)); ast_copy_string(chan->exten, save_exten, sizeof(chan->exten)); chan->priority = save_prio; if (bridge_cdr) { Index: main/pbx.c =================================================================== --- main/pbx.c (revision 243115) +++ main/pbx.c (working copy) @@ -4036,7 +4036,7 @@ ast_unlock_contexts(); if (!app) { ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority); - return -1; + return -ENOSYS; } if (c->context != context) ast_copy_string(c->context, context, sizeof(c->context));