From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: Vladislav Shpilevoy Subject: [PATCH 1/8] lua: fix box.error.raise Date: Mon, 16 Apr 2018 21:39:11 +0300 Message-Id: <860da7f4e8760673d6052614a5df1d4bdb67c06b.1523903144.git.v.shpilevoy@tarantool.org> In-Reply-To: References: In-Reply-To: References: To: tarantool-patches@freelists.org Cc: vdavydov.dev@gmail.com List-ID: It did not work because raise is implemented as __index metatable member, and error() is __call metatable member. The second one takes additional implicit argument - self. --- src/box/lua/error.cc | 78 +++++++++++++++++++++++++++++++++----------------- test/box/misc.result | 39 +++++++++++++++++++++++++ test/box/misc.test.lua | 18 ++++++++++++ 3 files changed, 108 insertions(+), 27 deletions(-) diff --git a/src/box/lua/error.cc b/src/box/lua/error.cc index 314907421..56cc2c563 100644 --- a/src/box/lua/error.cc +++ b/src/box/lua/error.cc @@ -42,25 +42,18 @@ extern "C" { #include "lua/utils.h" #include "box/error.h" -static int -luaT_error_raise(lua_State *L) +static void +luaT_error_create(lua_State *L, int top, int top_base) { uint32_t code = 0; const char *reason = NULL; const char *file = ""; unsigned line = 0; lua_Debug info; - /* lua_type(L, 1) == LUA_TTABLE - box.error table */ - int top = lua_gettop(L); - if (top <= 1) { - /* re-throw saved exceptions (if any) */ - if (box_error_last()) - luaT_error(L); - return 0; - } else if (top >= 2 && lua_type(L, 2) == LUA_TNUMBER) { - code = lua_tonumber(L, 2); + if (top >= top_base && lua_type(L, top_base) == LUA_TNUMBER) { + code = lua_tonumber(L, top_base); reason = tnt_errcode_desc(code); - if (top > 2) { + if (top > top_base) { /* Call string.format(reason, ...) to format message */ lua_getglobal(L, "string"); if (lua_isnil(L, -1)) @@ -69,24 +62,29 @@ luaT_error_raise(lua_State *L) if (lua_isnil(L, -1)) goto raise; lua_pushstring(L, reason); - for (int i = 3; i <= top; i++) + for (int i = top_base + 1; i <= top; i++) lua_pushvalue(L, i); - lua_call(L, top - 1, 1); + lua_call(L, top - top_base + 1, 1); reason = lua_tostring(L, -1); } else if (strchr(reason, '%') != NULL) { /* Missing arguments to format string */ luaL_error(L, "box.error(): bad arguments"); } - } else if (top == 2 && lua_istable(L, 2)) { - /* A special case that rethrows raw error (used by net.box) */ - lua_getfield(L, 2, "code"); - code = lua_tonumber(L, -1); - lua_pop(L, 1); - lua_getfield(L, 2, "reason"); - reason = lua_tostring(L, -1); - if (reason == NULL) - reason = ""; - lua_pop(L, 1); + } else if (top == top_base) { + if (lua_istable(L, top_base)) { + /* A special case that rethrows raw error (used by net.box) */ + lua_getfield(L, top_base, "code"); + code = lua_tonumber(L, -1); + lua_pop(L, 1); + lua_getfield(L, top_base, "reason"); + reason = lua_tostring(L, -1); + if (reason == NULL) + reason = ""; + lua_pop(L, 1); + } else if (luaL_iserror(L, top_base)) { + lua_error(L); + return; + } } else { luaL_error(L, "box.error(): bad arguments"); } @@ -104,8 +102,34 @@ raise: } say_debug("box.error() at %s:%i", file, line); box_error_set(file, line, code, "%s", reason); - luaT_error(L); - return 0; +} + +static int +luaT_error_call(lua_State *L) +{ + int top = lua_gettop(L); + if (top <= 1) { + /* Re-throw saved exceptions if any. */ + if (box_error_last()) + luaT_error(L); + return 0; + } + luaT_error_create(L, top, 2); + return luaT_error(L); +} + +static int +luaT_error_raise(lua_State *L) +{ + int top = lua_gettop(L); + if (top == 0) { + /* Re-throw saved exceptions if any. */ + if (box_error_last()) + luaT_error(L); + return 0; + } + luaT_error_create(L, top, 1); + return luaT_error(L); } static int @@ -214,7 +238,7 @@ box_lua_error_init(struct lua_State *L) { } lua_newtable(L); { - lua_pushcfunction(L, luaT_error_raise); + lua_pushcfunction(L, luaT_error_call); lua_setfield(L, -2, "__call"); lua_newtable(L); diff --git a/test/box/misc.result b/test/box/misc.result index 57717c4fe..2102e4a1c 100644 --- a/test/box/misc.result +++ b/test/box/misc.result @@ -176,6 +176,45 @@ box.error(box.error.UNSUPPORTED) --- - error: 'box.error(): bad arguments' ... +-- +-- box.error.raise not worked because it is __index method of +-- box.error and box.error() is the __call method. The second +-- one takes itself as the first argument. +-- +box.error(box.error.CREATE_SPACE, "space", "error") +--- +- error: 'Failed to create space ''space'': error' +... +box.error() +--- +- error: 'Failed to create space ''space'': error' +... +box.error.raise() +--- +- error: 'Failed to create space ''space'': error' +... +box.error.raise(box.error.CREATE_SPACE, "space", "error") +--- +- error: 'Failed to create space ''space'': error' +... +box.error.raise(box.error.UNKNOWN) +--- +- error: Unknown error +... +-- +-- Allow to rethrow error. +-- +_, err = pcall(box.error, box.error.UNKNOWN) +--- +... +box.error(err) +--- +- error: Unknown error +... +box.error.raise(err) +--- +- error: Unknown error +... ---------------- -- # box.stat ---------------- diff --git a/test/box/misc.test.lua b/test/box/misc.test.lua index b7bf600c3..299dc830f 100644 --- a/test/box/misc.test.lua +++ b/test/box/misc.test.lua @@ -52,6 +52,24 @@ box.error(box.error.UNSUPPORTED, "x", "x%s") box.error(box.error.UNSUPPORTED, "x") box.error(box.error.UNSUPPORTED) +-- +-- box.error.raise not worked because it is __index method of +-- box.error and box.error() is the __call method. The second +-- one takes itself as the first argument. +-- +box.error(box.error.CREATE_SPACE, "space", "error") +box.error() +box.error.raise() +box.error.raise(box.error.CREATE_SPACE, "space", "error") +box.error.raise(box.error.UNKNOWN) + +-- +-- Allow to rethrow error. +-- +_, err = pcall(box.error, box.error.UNKNOWN) +box.error(err) +box.error.raise(err) + ---------------- -- # box.stat ---------------- -- 2.15.1 (Apple Git-101)