[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: guarantees of exception safety in Lua
- From: "Peter Cawley" <lua@...>
- Date: Mon, 27 Oct 2008 17:12:51 +0000
While Lua as a language provides the guarantee that no memory will be
leaked, it is impossible to provide anything further at the language
level. As is the case with C++, exception guarantees can only be given
at the per-function or per-library level. If the author of the
function wants to provide invariants in the case of exceptions, then
they need to assume that every line may fail and restore invariants if
they have been modified.
2008/10/27 Roberto Ierusalimschy <roberto@inf.puc-rio.br>:
>> I was wondering what guarantees of exception safety[1] are provided in Lua.
>
> We do extensive testing about the safety of Lua. When we compile Lua
> in test mode, the allocation function (not luaM_realloc_) is redefined
> so that it throws an error when the total memory reaches a limit. Then
> we perform several tasks like this: we set this limit to memory_in_use
> (so that any attempt to allocate more memory fails) and then go on
> increasing it by 3 bytes each time, until we can complete the task. This
> ensures that we have memory fails in practically every allocation point
> in the code.
>
>
>> 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)
>
> This result is expected, is it not? "test" was interrupted by an
> exception (memory allocation error, caught by pcall) after
> incrementing x but before decrementing it. What value did you expect?
>
>
>> 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.
>
> The Lua stack is not visible for the users. Memory allocation errors
> may occur almost anywhere inside a Lua script.
>
>
>> 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);
>
> This patch is not correct: "Lua assumes that the allocator never fails
> when osize >= nsize." (http://www.lua.org/manual/5.1/manual.html#lua_Alloc)
>
> -- Roberto
>