From 62e014a08cd27d446f01b9e9f6be36f63ee96f12 Mon Sep 17 00:00:00 2001
From: Konstantin Osipov <kostja.osipov@gmail.com>
Date: Fri, 16 Dec 2011 19:15:03 +0400
Subject: [PATCH] A fix and a test case for Bug#901674

A fix and a test case for Bug#901674
"No way to inspect exceptions from Box in Lua"

Implenent pcall which works correctly with Objective C
exceptions.
---
 core/tarantool_lua.m         | 34 +++++++++++++++++++++++++++++++++-
 doc/user/stored-programs.xml |  2 +-
 test/box/lua.result          | 22 ++++++++++++++++++++++
 test/box/lua.test            |  8 ++++++++
 4 files changed, 64 insertions(+), 2 deletions(-)

diff --git a/core/tarantool_lua.m b/core/tarantool_lua.m
index a9d6efa087..04f6dcb3de 100644
--- a/core/tarantool_lua.m
+++ b/core/tarantool_lua.m
@@ -435,7 +435,7 @@ box_lua_fiber_run(void *arg __attribute__((unused)))
 		 * cancel() is synchronous.
 		 */
 		lua_settop(L, 0); /* pop any possible garbage */
-		lua_pushboolean(L, 0); /* completion status */
+		lua_pushboolean(L, false); /* completion status */
 		lua_pushstring(L, e->errmsg); /* error message */
 	} @finally {
 		/*
@@ -699,6 +699,37 @@ lbox_print(struct lua_State *L)
 	return 0;
 }
 
+/**
+ * Redefine lua 'pcall' built-in to correctly handle exceptions,
+ * produced by 'box' C functions.
+ *
+ * See Lua documentation on 'pcall' for additional information.
+ */
+
+static int
+lbox_pcall(struct lua_State *L)
+{
+	/*
+	 * Lua pcall() returns true/false for completion status
+	 * plus whatever the called function returns.
+	 */
+	@try {
+		lua_call(L, lua_gettop(L) - 1, LUA_MULTRET);
+		lua_pushboolean(L, true); /* push completion status */
+		lua_insert(L, 1); /* move 'true' to stack start */
+	} @catch (ClientError *e) {
+		/*
+		 * Note: FiberCancelException passes through this
+		 * catch and thus leaves garbage on coroutine
+		 * stack.
+		 */
+		lua_settop(L, 0); /* pop any possible garbage */
+		lua_pushboolean(L, false); /* completion status */
+		lua_pushstring(L, e->errmsg); /* error message */
+	}
+	return lua_gettop(L);
+}
+
 /** A helper to register a single type metatable. */
 void
 tarantool_lua_register_type(struct lua_State *L, const char *type_name,
@@ -731,6 +762,7 @@ tarantool_lua_init()
 	lua_pop(L, 1);
 	tarantool_lua_register_type(L, fiberlib_name, lbox_fiber_meta);
 	lua_register(L, "print", lbox_print);
+	lua_register(L, "pcall", lbox_pcall);
 	L = mod_lua_init(L);
 	lua_settop(L, 0); /* clear possible left-overs of init */
 	return L;
diff --git a/doc/user/stored-programs.xml b/doc/user/stored-programs.xml
index 13dbc13b21..cb2c0fc2d6 100644
--- a/doc/user/stored-programs.xml
+++ b/doc/user/stored-programs.xml
@@ -155,7 +155,7 @@ Call ERROR, Space 99 is disabled (ER_SPACE_DISABLED)
 localhost> lua pcall(box.insert, 99, 1, 'test')
 ---
  - false
- - C++ exception
+ - Space 99 is disabled
 ...
 </computeroutput></programlisting>
   </para>
diff --git a/test/box/lua.result b/test/box/lua.result
index 5ed71536b4..358715c3a2 100644
--- a/test/box/lua.result
+++ b/test/box/lua.result
@@ -806,3 +806,25 @@ Found 25 tuples:
 lua box.space[0]:truncate()
 ---
 ...
+
+# A test case for Bug#901674
+# No way to inspect exceptions from Box in Lua
+
+lua pcall(box.insert, 99, 1, 'test')
+---
+ - false
+ - Space 99 is disabled
+...
+lua pcall(box.insert, 0, 1, 'hello')
+---
+ - true
+ - 1: {'hello'}
+...
+lua pcall(box.insert, 0, 1, 'hello')
+---
+ - false
+ - Tuple already exists
+...
+lua box.space[0]:truncate()
+---
+...
diff --git a/test/box/lua.test b/test/box/lua.test
index 0a856b8b42..f43352b283 100644
--- a/test/box/lua.test
+++ b/test/box/lua.test
@@ -234,3 +234,11 @@ exec admin "lua box.space[0]:insert(4, 'world')"
 exec admin "lua box.space[0]:insert(5, 'hello world')"
 exec sql "call box.crossjoin('0', '0', '10000')"
 exec admin "lua box.space[0]:truncate()"
+print """
+# A test case for Bug#901674
+# No way to inspect exceptions from Box in Lua
+"""
+exec admin "lua pcall(box.insert, 99, 1, 'test')"
+exec admin "lua pcall(box.insert, 0, 1, 'hello')"
+exec admin "lua pcall(box.insert, 0, 1, 'hello')"
+exec admin "lua box.space[0]:truncate()"
-- 
GitLab