[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: guarantees of exception safety in Lua
- From: "David Manura" <dm.lua@...>
- Date: Sat, 25 Oct 2008 18:30:48 -0400
I was wondering what guarantees of exception safety[1] are provided in Lua.
To help in testing, the below patch to Lua prints "[r]" upon each
allocation attempt and implements a function failalloc(n) that
schedules a memory allocation failure in the next n-th allocation.
This is used in the following example. Here, g() has a memory
allocation failure when trying to grow that stack in the OP_CALL.
This causes the program to prints out that x is 2 despite the intended
invariant that x == 1.
local function g()
local x=1,2,3,4,5,6,7,8,9,10, 11,12,13,14,15,16,17,18,19,20,
21,22,23,24,25,26,27,28
end
local x = 1
local function test()
x = x + 1
g()
x = x - 1
end
failalloc(1)
local ok,msg = pcall(test)
failalloc(0)
print(x, ok, msg)
Although the Lua Reference Manual[2] defines the behavior of stack
growing for C functions, I don't think it does so for Lua functions.
[1] http://en.wikipedia.org/wiki/Exception_handling
[2] http://www.lua.org/manual/5.1/manual.html#3.2
diff -ur lua-5.1.4/src/lbaselib.c lua-mem/src/lbaselib.c
--- lua-5.1.4/src/lbaselib.c 2008-02-14 11:46:22.000000000 -0500
+++ lua-mem/src/lbaselib.c 2008-10-25 16:36:44.437500000 -0400
@@ -19,7 +19,12 @@
#include "lauxlib.h"
#include "lualib.h"
+extern int g_failalloc;
+static int luaB_failalloc(lua_State *L) {
+ g_failalloc = lua_tonumber(L, 1);
+ return 0;
+}
/*
@@ -449,6 +454,7 @@
{"collectgarbage", luaB_collectgarbage},
{"dofile", luaB_dofile},
{"error", luaB_error},
+ {"failalloc", luaB_failalloc},
{"gcinfo", luaB_gcinfo},
{"getfenv", luaB_getfenv},
{"getmetatable", luaB_getmetatable},
diff -ur lua-5.1.4/src/lmem.c lua-mem/src/lmem.c
--- lua-5.1.4/src/lmem.c 2007-12-27 08:02:25.000000000 -0500
+++ lua-mem/src/lmem.c 2008-10-25 17:04:41.062500000 -0400
@@ -6,6 +6,7 @@
#include <stddef.h>
+#include <stdio.h>
#define lmem_c
#define LUA_CORE
@@ -42,6 +43,7 @@
#define MINSIZEARRAY 4
+int g_failalloc = 0;
void *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elems,
int limit, const char *errormsg) {
@@ -69,13 +71,14 @@
}
-
/*
** 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));
+ printf("[r]");
+ if (g_failalloc && --g_failalloc == 0) { luaD_throw(L, LUA_ERRMEM); }
block = (*g->frealloc)(g->ud, block, osize, nsize);
if (block == NULL && nsize > 0)
luaD_throw(L, LUA_ERRMEM);