[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: is it possible to make longjmp-free Lua?
- From: "Juris Kalnins" <juris@...>
- Date: Wed, 29 Jul 2009 10:18:48 +0300
A much better solution would be for Lua to provide a version
lua_checkstack that doesn't longjump. Preventing longjumps is a
recurring problem of mine that pushes toward refactoring code in a way
I don't want or going through contortions.
I started experimenting with a code like in a patch below[*], and
immediately stepped on rakes with luaD_throw usage in the Lua core.
One case is the throw that you are talking about (ldo.c):
/*
** generic allocation routine.
*/
void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t
nsize) {
global_State *g = G(L);
lua_assert((osize == 0) == (block == NULL));
block = (*g->frealloc)(g->ud, block, osize, nsize);
if (block == NULL && nsize > 0)
luaD_throw(L, LUA_ERRMEM); <<<<<<<<<<<<<<<<<<<<<<< here, and
making THROW a nop breaks everything :(
lua_assert((nsize == 0) == (block == NULL));
g->totalbytes = (g->totalbytes - osize) + nsize;
return block;
}
This is the only place where lua_checkstack can throw that I found. But a
big one.
Because of this Lua code always assumes that memory allocation is
successful.
So going that way would mean patching big part of the core.
I still feel that it is worth it in a long run.
However, if you only need to be assured that lua_checkstack will not
throw, you can do something like:
safe_checkstack(L, n) {
void *p = luaM_malloc(L, 0, 0, how_much_mem_it_will_take(n));
if (!p) return 0;
luaM_free(p);
lua_checkstack(L, n);
return 1;
}
[*] a toy patch:
diff -Nurbd ../../lua-5.1.4/src/luaconf.h ./luaconf.h
--- ../../lua-5.1.4/src/luaconf.h 2008-02-11 18:25:08.000000000 +0200
+++ ./luaconf.h 2009-07-28 11:42:14.000000000 +0300
@@ -603,7 +604,19 @@
** compiling as C++ code, with _longjmp/_setjmp when asked to use them,
** and with longjmp/setjmp otherwise.
*/
-#if defined(__cplusplus)
+
+#if ! defined(LUA_NOUNWIND)
+#define LUAI_HASERROR(L) 0
+#endif
+
+#if defined(LUA_NOUNWIND)
+/* Slow exceptions without stack unwinding */
+#define LUAI_HASERROR(L) lua_haserror(L)
+#define LUAI_THROW(L,c) (void) 0
+#define LUAI_TRY(L,c,a) { a }
+#define luai_jmpbuf int /* dummy variable */
+
+#elif defined(__cplusplus)
/* C++ exceptions */
#define LUAI_THROW(L,c) throw(c)
#define LUAI_TRY(L,c,a) try { a } catch(...) \
diff -Nurbd ../../lua-5.1.4/src/lua.h ./lua.h
--- ../../lua-5.1.4/src/lua.h 2008-08-06 16:30:12.000000000 +0300
+++ ./lua.h 2009-07-28 09:50:14.000000000 +0300
@@ -112,6 +112,9 @@
LUA_API lua_State *(lua_newthread) (lua_State *L);
LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf);
+#if defined(LUA_NOUNWIND)
+LUA_API int lua_haserror(lua_State *);
+#endif
- References:
- is it possible to make longjmp-free Lua?, Juris Kalnins
- Re: is it possible to make longjmp-free Lua?, Jerome Vuarand
- Re: is it possible to make longjmp-free Lua?, Juris Kalnins
- Re: is it possible to make longjmp-free Lua?, Jerome Vuarand
- Re: is it possible to make longjmp-free Lua?, Juris Kalnins
- Re: is it possible to make longjmp-free Lua?, Juris Kalnins
- Re: is it possible to make longjmp-free Lua?, Mark Hamburg
- Re: is it possible to make longjmp-free Lua?, David Manura
- Re: is it possible to make longjmp-free Lua?, Mark Hamburg
- Re: is it possible to make longjmp-free Lua?, David Manura