diff --git a/src/lua/session.m b/src/lua/session.m index 523d8d7c0715dbe835d4bc355c8ea1ed8c65179e..23bc997d9382103ce1c0330f3fcdea37638a821e 100644 --- a/src/lua/session.m +++ b/src/lua/session.m @@ -91,7 +91,7 @@ lbox_session_peer(struct lua_State *L) struct lbox_session_trigger { struct session_trigger *trigger; - int coro_ref; + int ref; }; static struct lbox_session_trigger on_connect = @@ -104,26 +104,21 @@ lbox_session_run_trigger(void *param) { struct lbox_session_trigger *trigger = param; /* Copy the referenced callable object object stack. */ - lua_rawgeti(tarantool_L, LUA_REGISTRYINDEX, trigger->coro_ref); + lua_State *L = lua_newthread(tarantool_L); + int coro_ref = luaL_ref(tarantool_L, LUA_REGISTRYINDEX); + lua_rawgeti(tarantool_L, LUA_REGISTRYINDEX, trigger->ref); + /** Move the function to be called to the new coro. */ + lua_xmove(tarantool_L, L, 1); - struct lua_State *coro_L = lua_tothread(tarantool_L, -1); - lua_pop(tarantool_L, 1); - /* - * If there was junk from previous invocation of the - * trigger, clear it, only leaving on the stack the chunk - * to be run. The stack may be polluted when previous - * invocation ended up with an error. - */ - lua_settop(coro_L, 1); - /* lua_call pops the function, make a copy */ - lua_pushvalue(coro_L, -1); @try { - lua_call(coro_L, 0, 0); + lua_call(L, 0, 0); } @catch (tnt_Exception *e) { @throw; } @catch (...) { tnt_raise(ClientError, :ER_PROC_LUA, - lua_tostring(coro_L, -1)); + lua_tostring(L, -1)); + } @finally { + luaL_unref(tarantool_L, LUA_REGISTRYINDEX, coro_ref); } } @@ -137,36 +132,31 @@ lbox_session_set_trigger(struct lua_State *L, luaL_error(L, "session.on_connect(chunk): bad arguments"); } - struct lua_State *coro_L; - - if (trigger->coro_ref != LUA_NOREF) { - lua_rawgeti(L, LUA_REGISTRYINDEX, trigger->coro_ref); - coro_L = lua_tothread(L, -1); - lua_pop(L, 1); /* pop the coro. */ - /* If there was junk from previous invocation, clear it. */ - lua_settop(coro_L, 1); + /* Pop the old trigger */ + if (trigger->ref != LUA_NOREF) { + lua_rawgeti(L, LUA_REGISTRYINDEX, trigger->ref); + luaL_unref(L, LUA_REGISTRYINDEX, trigger->ref); } else { - coro_L = lua_newthread(L); - /* Reference the new thread and pop it. */ - trigger->coro_ref = luaL_ref(L, LUA_REGISTRYINDEX); - lua_pushnil(coro_L); + lua_pushnil(L); } - /** Move the chunk to the coroutine in will be run in. */ - lua_xmove(L, coro_L, 1); - /* Return the old chunk. */ - lua_insert(coro_L, -2); - lua_xmove(coro_L, L, 1); + /* * Set or clear the trigger. Return the old value of the * trigger. */ - if (lua_type(coro_L, -1) == LUA_TNIL) { + if (lua_type(L, -2) == LUA_TNIL) { + trigger->ref = LUA_NOREF; trigger->trigger->trigger = NULL; trigger->trigger->param = NULL; } else { + /* Move the trigger to the top of the stack. */ + lua_insert(L, -2); + /* Reference the new trigger. Pops it. */ + trigger->ref = luaL_ref(L, LUA_REGISTRYINDEX); trigger->trigger->trigger = lbox_session_run_trigger; trigger->trigger->param = trigger; } + /* Return the old trigger. */ return 1; }