[PATCH 1/8] lua: fix box.error.raise

Vladislav Shpilevoy v.shpilevoy at tarantool.org
Mon Apr 16 21:39:11 MSK 2018


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)




More information about the Tarantool-patches mailing list