Fix lua goto detection to prevent unexpected behavior with confbridge
authorKinsey Moore <kmoore@digium.com>
Fri, 6 Jan 2012 21:26:16 +0000 (21:26 +0000)
committerKinsey Moore <kmoore@digium.com>
Fri, 6 Jan 2012 21:26:16 +0000 (21:26 +0000)
A bug in the pbx_lua goto detection was causing the dialplan to hangup
unexpectedly after confbridge exited if it had called lua dialplan code during
execution.

Patch-by: Timo Teras
Acked-by: Matt Nicholson
(closes issue ASTERISK-18976)
........

Merged revisions 349928 from http://svn.asterisk.org/svn/asterisk/branches/10

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@349929 65c4cc65-6c06-0410-ace0-fbb531ad65f3

pbx/pbx_lua.c

index 0dccfe6..2c14874 100644 (file)
@@ -94,7 +94,6 @@ static void lua_create_variable_metatable(lua_State *L);
 static void lua_create_application_metatable(lua_State *L);
 static void lua_create_autoservice_functions(lua_State *L);
 static void lua_create_hangup_function(lua_State *L);
-static void lua_detect_goto(lua_State *L);
 static void lua_concat_args(lua_State *L, int start, int nargs);
 
 static void lua_state_destroy(void *data);
@@ -213,19 +212,10 @@ static int lua_pbx_exec(lua_State *L)
        chan = lua_touserdata(L, -1);
        lua_pop(L, 1);
        
+       context = ast_strdupa(chan->context);
+       exten = ast_strdupa(chan->exten);
+       priority = chan->priority;
        
-       lua_getfield(L, LUA_REGISTRYINDEX, "context");
-       context = ast_strdupa(lua_tostring(L, -1));
-       lua_pop(L, 1);
-       
-       lua_getfield(L, LUA_REGISTRYINDEX, "exten");
-       exten = ast_strdupa(lua_tostring(L, -1));
-       lua_pop(L, 1);
-       
-       lua_getfield(L, LUA_REGISTRYINDEX, "priority");
-       priority = lua_tointeger(L, -1);
-       lua_pop(L, 1);
-
        lua_concat_args(L, 2, nargs);
        data = lua_tostring(L, -1);
 
@@ -256,75 +246,51 @@ static int lua_pbx_exec(lua_State *L)
                return lua_error(L);
        }
 
-       lua_detect_goto(L);
-
-       return 0;
-}
-
-/*!
- * \brief Detect if a Goto or other dialplan jump has been executed and return
- * control to the pbx engine.
- */
-static void lua_detect_goto(lua_State *L)
-{
-       struct ast_channel *chan;
-
-       lua_getfield(L, LUA_REGISTRYINDEX, "channel");
-       chan = lua_touserdata(L, -1);
-       lua_pop(L, 1);
-
-       /* check context */
-       lua_getfield(L, LUA_REGISTRYINDEX, "context");
-       lua_pushstring(L, chan->context);
-       if (!lua_equal(L, -1, -2)) {
+       if (strcmp(context, chan->context)) {
+               lua_pushstring(L, context);
+               lua_pushstring(L, chan->context);
                lua_pushliteral(L, "context");
-               goto e_goto_detected;
-       }
-       lua_pop(L, 2);
-
-       /* check exten */
-       lua_getfield(L, LUA_REGISTRYINDEX, "exten");
-       lua_pushstring(L, chan->exten);
-       if (!lua_equal(L, -1, -2)) {
+       } else if (strcmp(exten, chan->exten)) {
+               lua_pushstring(L, exten);
+               lua_pushstring(L, chan->exten);
                lua_pushliteral(L, "exten");
-               goto e_goto_detected;
-       }
-       lua_pop(L, 2);
-
-       /* check priority */
-       lua_getfield(L, LUA_REGISTRYINDEX, "priority");
-       lua_pushinteger(L, chan->priority);
-       if (!lua_equal(L, -1, -2)) {
+       } else if (priority != chan->priority) {
+               lua_pushinteger(L, priority);
+               lua_pushinteger(L, chan->priority);
                lua_pushliteral(L, "priority");
-               goto e_goto_detected;
+       } else {
+               /* no goto - restore the original position back
+                * to lua state, in case this was a recursive dialplan
+                * call (a dialplan application re-entering dialplan) */
+               lua_update_registry(L, context, exten, priority);
+               return 0;
        }
-       lua_pop(L, 2);
-       return;
-
-e_goto_detected:
-       /* format our debug message */
-       lua_insert(L, -3);
 
-       lua_pushliteral(L, " changed from ");
+       /* goto detected - construct error message */
        lua_insert(L, -3);
-
-       lua_pushliteral(L, " to ");
-       lua_insert(L, -2);
-
-       lua_concat(L, 5);
-
-       ast_debug(2, "Goto detected: %s\n", lua_tostring(L, -1));
-       lua_pop(L, 1);
-
-       /* let the lua engine know it needs to return control to the pbx */
-       lua_pushinteger(L, LUA_GOTO_DETECTED);
+                                                                                                       
+       lua_pushliteral(L, " changed from ");                                                       
+       lua_insert(L, -3);                                                                             
+                                                                                                        
+       lua_pushliteral(L, " to ");                                                                   
+       lua_insert(L, -2);                                                                             
+                                                                                                        
+       lua_concat(L, 5);                                                                               
+                                                                                                        
+       ast_debug(2, "Goto detected: %s\n", lua_tostring(L, -1));                                       
+       lua_pop(L, 1);                                                                             
+                                                                                                        
+       /* let the lua engine know it needs to return control to the pbx */                           
+       lua_pushinteger(L, LUA_GOTO_DETECTED);                                                     
        lua_error(L);
+
+       return 0;
 }
 
 /*!
  * \brief [lua_CFunction] Used to get the value of a variable or dialplan
  * function (for access from lua, don't call directly)
- * 
+ *
  * The value of the variable or function is returned.  This function is the
  * 'get()' function in the following example as would be seen in
  * extensions.lua.