Hi all
I stumble on oom in luajit scripts now and then in my code.
It's fixed usually by calling collectgarbage('step') in loops.
However I'd to mitigate the risk of sudden crash/exit when there is
plenty of free memory available, but it has not been garbage-collected
yet.
/ And yes, for me it's much more important not to loose the state vs.
sudden latency spike.
I've made a small test against current HEAD and small patch possibly
fixing the issue. See __gc.lua and gc_on_oom.patch.
Could anybody give opinion on the patch?
Also is there any downside of this approach (besides sudden full gc)?
BR,
Denis
diff --git a/src/lj_gc.c b/src/lj_gc.c
index 7c70746..bd74f70 100644
--- a/src/lj_gc.c
+++ b/src/lj_gc.c
@@ -803,12 +803,29 @@ void lj_gc_barriertrace(global_State *g, uint32_t traceno)
/* -- Allocator ----------------------------------------------------------- */
+void *alloc_mem_gc(lua_State *L, void *p, GCSize osz, GCSize nsz)
+{
+ global_State *g = G(L);
+ p = g->allocf(g->allocd, p, osz, nsz);
+ if (p == NULL && nsz > 0)
+ {
+ // allocation failed...
+ //lj_err_mem(L);
+
+ //try again after gc
+ lj_gc_fullgc(L);
+ p = g->allocf(g->allocd, p, osz, nsz);
+ }
+
+ return p;
+}
+
/* Call pluggable memory allocator to allocate or resize a fragment. */
void *lj_mem_realloc(lua_State *L, void *p, GCSize osz, GCSize nsz)
{
global_State *g = G(L);
lua_assert((osz == 0) == (p == NULL));
- p = g->allocf(g->allocd, p, osz, nsz);
+ p = alloc_mem_gc(L, p, osz, nsz);
if (p == NULL && nsz > 0)
lj_err_mem(L);
lua_assert((nsz == 0) == (p == NULL));
@@ -821,7 +838,7 @@ void *lj_mem_realloc(lua_State *L, void *p, GCSize osz,
GCSize nsz)
void * LJ_FASTCALL lj_mem_newgco(lua_State *L, GCSize size)
{
global_State *g = G(L);
- GCobj *o = (GCobj *)g->allocf(g->allocd, NULL, 0, size);
+ GCobj *o = (GCobj *)alloc_mem_gc(L, NULL, 0, size);
if (o == NULL)
lj_err_mem(L);
lua_assert(checkptrGC(o));
@@ -844,4 +861,3 @@ void *lj_mem_grow(lua_State *L, void *p, MSize *szp, MSize
lim, MSize esz)
*szp = sz;
return p;
}
-
collectgarbage("setstepmul",20)
collectgarbage("setpause",60)
ffi=require('ffi')
ffi.cdef("void* malloc(size_t size); void free(void* ptr);")
while true do
local size=10
local arr = ffi.gc(ffi.C.malloc(size), ffi.C.free)
end
print "ok"