lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


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