[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: LuaJIT, ObjectiveC, @throw in lua_atpanic, clang, infinite recursion
- From: Konstantin Osipov <kostja.osipov@...>
- Date: Wed, 20 Jun 2012 17:24:52 +0400
Hello,
There was a similar discussion taking place in 2010,
http://lua-users.org/lists/lua-l/2010-04/msg00441.html, but it
doesn't seem to clarify our case.
We use LuaJIT Beta9 and experience intermittent trouble with
exceptions thrown from lua_atpanic handler. Beta10 demonstrates
the same behaviour.
The problem seems to depend on the compiler version (in case of
gcc), language flavour (C++ vs Objective C), platform (32-bit
Linux, 64-bit Linux, Darwin).
The common part is that the problem always manifests itself
in almost the same way: an exception, thrown from an at_panic handler,
instead of percolating up the stack ends up in the same stack
frame, and recursively executes the at_panic handler again.
I attach two test cases (in C++ and Objective C) which can
be used to demonstrate the issue.
I would appreciate any help, explanation of the cause, or
description of a workaround.
Being able to propagate exceptions through LuaJIT stack is a nice
feature of LuaJIT and we use it quite extensively.
Thank you,
---------------------------------------------------------------
#include <objc/Object.h>
#include <objc/runtime.h>
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
@interface Exception: Object {
char *errmsg;
}
+ (id) alloc;
- (id) init: (char*) msg;
@end
@implementation Exception
+ (id) alloc
{
static char buf[10000];
Exception *new = (Exception *) buf;
object_setClass(new, self);
return new;
}
- (id) init: (char*) msg;
{
self = [super init];
errmsg = msg;
return self;
}
@end
void test(struct lua_State *L)
{
const char *format = luaL_checkstring(L, 1);
}
static int
box_lua_panic(struct lua_State *L)
{
static int invocation_count = 0;
if (invocation_count++ == 0)
@throw [[Exception alloc] init: "message"];
abort();
}
int main()
{
lua_State *L = luaL_newstate();
luaL_openlibs(L);
lua_atpanic(L, box_lua_panic);
@try {
test(L);
} @catch (Exception *e) {
printf("exception handled\n");
}
lua_close(L);
}
----------------------------------------------------------------------
An example of how it works and breaks:
kostja@atlas:~$ clang++ -fobjc-exceptions
-I/home/kostja/LuaJIT-2.0.0-beta9/src tarantool_lua.m -L
/home/kostja/LuaJIT-2.0.0-beta9/src -lluajit -ldl -lobjc; ./a.out
[1] 20790 abort (core dumped) ./a.out
kostja@atlas:~$ g++ -fobjc-exceptions
-I/home/kostja/LuaJIT-2.0.0-beta9/src tarantool_lua.m -L
/home/kostja/LuaJIT-2.0.0-beta9/src -lluajit -ldl -lobjc; ./a.out
exception handled
kostja@atlas:~$ clang++ -fexceptions
-I/home/kostja/LuaJIT-2.0.0-beta9/src tarantool_lua.m -L
/home/kostja/LuaJIT-2.0.0-beta9/src -lluajit -ldl -lobjc; ./a.out
exception handled
--------------------------------------------------------------
#include <cstdlib>
#include <lua.hpp>
static int panic = 0;
static int lua_panic_cb(lua_State *L) {
if (!panic++)
throw 0;
abort();
return 0;
}
int
main(int argc, char * argv[])
{
lua_State *L = luaL_newstate();
if (L == NULL)
return 1;
lua_atpanic(L, lua_panic_cb);
try {
lua_pushstring(L, "uncallable");
lua_call(L, 0, LUA_MULTRET);
} catch (...) {
/* If we're lucky, we should get here. */
}
lua_close(L);
return 0;
}
--------------------------------------------------------------
--
http://tarantool.org - an efficient, extensible in-memory data store