Re: LuaJIT, ObjectiveC, @throw in lua_atpanic, clang, infinite recursion

  • From: Konstantin Osipov <kostja@xxxxxxxxxxxxx>
  • To: luajit@xxxxxxxxxxxxx
  • Date: Wed, 27 Jun 2012 11:44:59 +0400

* Mike Pall <mike-1206@xxxxxxxxxx> [12/06/27 10:43]:

> > Is there any other way to ensure that lua_error() throws an
> > instance of our application exception class?
> LuaJIT's error handling uses native exceptions on x64 and it's own
> setjmp/longjmp-style exception handling on all other platforms.

In other words, instead of the current idiom:

-1------------------------------------
static int
box_lua_panic(struct lua_State *L)
{
        @throw [ClientError alloc] init: ER_PROC_LUA  :lua_tostring(L, -1)];
        return 0;
}

lua_atpanic(L, box_lua_panic);

@try {
        lua_call(L, lua_gettop(L) - 1, LUA_MULTRET);
} @catch (ClientError *e) {
    ...
}
-------------------------------------
    
We should be using catch(...) (provided we use external unwinding,
and we do):

-2----------------------------------
@try {
        lua_call(L, lua_gettop(L) - 1, LUA_MULTRET);
} @catch (ClientError *e) { /* for exceptions thrown by C code */
    ...
} @catch (id e) { /* for Lua errors */
    const char *msg = lua_tostring(L, -1);
    ...
}
------------------------------------

Is snippet #2 correct?

> You *may* select native exceptions on POSIX systems using DWARF2
> stack unwinding with -DLUAJIT_UNWIND_EXTERNAL. However, you may
> need to recompile all of your C code -- see the big comment block
> in src/lj_err.c for details.

Yes, we've read this comment and it's exactly how we compile.

> > > So always wrap your code in lua_pcall(). In fact, in LuaJIT it has
> > > the same cost as a lua_call(), so there's no reason not to use it.
> > Up to now we relied (maybe not in a fully correct way)
> > on LuaJIT exception interoperability documented at 
> > http://luajit.org/extensions.html
> > Do you advise against it in our case?
> If you end up in the atpanic handler, something went wrong with
> exception interoperability.
> I've assumed your problem is related to throwing an exception from
> the atpanic handler (which is a big no-no). But you should never
> end up at the atpanic handler in the first place.

We do not use lua_pcall at all, and lua_call ends up in atpanic handler
in case of any call to luaL_error()/error().

I guess you're saying that we must run our code in protected
environment regardless of whether we choose external or internal
stack unwinding?

The reason we don't do it, is that in this case any native C++
exception is converted to a Lua error with text "C++ exception",
whereas we'd like it to reach our @catch block instead.

> Please send me the assembler output (-S -masm=intel) of the
> minimal ObjC and C++ test programs on the affected platforms by
> mail and I'll try to investigate. Thank you!

Thank you very much. I will, once I get all the details right.

> > It works well (with a few compile tricks), when compiling with gcc
> > on FreeBSD and Linux, both 32 bit and 64 bit.
> Umm, so you've used -DLUAJIT_UNWIND_EXTERNAL on the 32 bit platforms?

Yes.

> If you can control the compiler versions, then you should be set.

Excellent. As soon as I figure out how to *not* use lua_atpanic,
I'll repeat my tests -- maybe throwing an exception from lua_atpanic
function was the remaining source of the trouble.

-- 
http://tarantool.org - an efficient, extensible in-memory data store

Other related posts: