lupa icon indicating copy to clipboard operation
lupa copied to clipboard

Add option to limit the memory usage of Lua code

Open Le0Developer opened this issue 2 years ago • 13 comments

Closes #211.

Le0Developer avatar May 08 '22 13:05 Le0Developer

It seems like LuaJIT does not support a custom allocator in lua_newstate on 64bit.

See the following and failing tests:

Make sure you use luaL_newstate. Avoid using lua_newstate, since this uses the (slower) default memory allocator from your system (no support for this on 64 bit architectures).

  • https://luajit.org/install.html

Le0Developer avatar May 20 '22 09:05 Le0Developer

It seems like LuaJIT does not support a custom allocator in lua_newstate on 64bit.

Hmm. That is annoying. Then we should raise an exception when we detect that case and users request a custom allocator.

scoder avatar May 21 '22 21:05 scoder

Setting max_memory to None will now use the default lua allocator. Also added documentation for set_max_memory() and max_memory.

set_max_memory() also a strict option now, which will raise an exception if you try to set max_memory to a value lower than currently used.

Le0Developer avatar May 22 '22 11:05 Le0Developer

Just tested running LuaJIT 2.1.0-beta3 and it works on 64bit. 🤷

Following is a patch that disallows LuaJIT on 64bit, if needed:

diff --git a/lupa/lua.pxd b/lupa/lua.pxd
index 35d4b6e15a4fc18e3deb20353be72cae4ebaee86..72cdce030bfaf13db38af6d97aed66c85f55eacf 100644
--- a/lupa/lua.pxd
+++ b/lupa/lua.pxd
@@ -266,6 +266,13 @@ cdef extern from "lua.h" nogil:
         int i_ci               #           active function */
 
 
+################################################################################
+# luajit.h
+################################################################################
+
+cdef extern from "luajit.h" nogil:
+    int LUAJIT_VERSION_NUM
+
 ################################################################################
 # lauxlib.h
 ################################################################################
@@ -465,11 +472,18 @@ cdef extern from * nogil:
     #if LUA_VERSION_NUM < 502
     #define lua_pushglobaltable(L)  lua_pushvalue(L, LUA_GLOBALSINDEX)
     #endif
+
+    #if defined LUAJIT_VERSION_NUM && UINTPTR_MAX == 0xffffffffffffffff
+    #define IS_LUAJIT64 1
+    #else
+    #define IS_LUAJIT64 0
+    #endif
     """
     int read_lua_version(lua_State *L)
     int lua_isinteger(lua_State *L, int idx)
     lua_Integer lua_tointegerx (lua_State *L, int idx, int *isnum)
     void lua_pushglobaltable (lua_State *L)
+    char IS_LUAJIT64
 
 cdef extern from *:
     # Limits for Lua integers (in Lua<5.3: PTRDIFF_MIN, PTRDIFF_MAX)
diff --git a/lupa/_lupa.pyx b/lupa/_lupa.pyx
index 22656680343b1c6e9f97ef8adf972df9958e614a..c173d9a9376339e2dfec982e04ca5ca9b7a8b6d2 100644
--- a/lupa/_lupa.pyx
+++ b/lupa/_lupa.pyx
@@ -263,6 +263,9 @@ cdef class LuaRuntime:
                   bint register_eval=True, bint unpack_returned_tuples=False,
                   bint register_builtins=True, overflow_handler=None,
                   max_memory=None):
+        if lua.IS_LUAJIT64 and max_memory is not None:
+            raise RuntimeError("max_memory is not supported on 64bit LuaJIT")
+        
         cdef lua_State* L
 
         self._memory_left = 0

Le0Developer avatar May 22 '22 12:05 Le0Developer

set_max_memory() also a strict option now, which will raise an exception if you try to set max_memory to a value lower than currently used.

I'd rather expose the current memory usage as readonly attribute and let users do their own checks. That seems more generally useful.

scoder avatar May 22 '22 13:05 scoder

Added memory_used

Le0Developer avatar May 22 '22 13:05 Le0Developer

There's still a test failure. Maybe you could look into that? I'd like to release Lupa 2.0 soon and this would be a nice addition.

scoder avatar Aug 03 '22 16:08 scoder

Unable to reproduce the test failure locally but I think that should've fixed it.

Le0Developer avatar Aug 03 '22 19:08 Le0Developer

I am getting no more test failures locally (running with 53 and 54)

Le0Developer avatar Aug 07 '22 20:08 Le0Developer

How long will lupa still support py2? It's been EOL for over 1.5 years.

Which doesn't mean that people aren't using it any more. I'll support Py2 as long as it's easy to do, which it still is.

scoder avatar Aug 08 '22 07:08 scoder

Test failure seems unrelated and can't reproduce

Le0Developer avatar Sep 18 '22 12:09 Le0Developer

I'm a Cython noob, so no idea how to fix this 🤷

Error compiling Cython file:
------------------------------------------------------------
...
    cdef bytes _source_encoding
    cdef object _attribute_filter
    cdef object _attribute_getter
    cdef object _attribute_setter
    cdef bint _unpack_returned_tuples
    cdef MemoryStatus _memory_status
                     ^
------------------------------------------------------------

lupa/lua53.pyx:260:22: Variable type 'MemoryStatus' is incomplete

Le0Developer avatar Sep 26 '22 07:09 Le0Developer

All test succeeding locally now! 🎉

Le0Developer avatar Sep 26 '22 08:09 Le0Developer

Thanks!

scoder avatar Apr 03 '23 13:04 scoder