From 07b0c8437160d77f92ca25b9c62922a76df059a1 Mon Sep 17 00:00:00 2001 From: Evan Wies Date: Fri, 1 Nov 2024 11:35:07 -0400 Subject: [PATCH] Build without Lua scripting via USE_LUA (#1204) Adds the ability to disable Lua scripting using the build conifguration `USE_LUA`. This will prevent the building of the Lua static library and will keep Lua and most Lua scripting internals out of the build. This approach strived to minimize the change surface, stubbing out keys requried functions and otherwise `ifdef`ing out large swathes of code. The base Lua scripting commands like `EVAL` remain intact, but reply with an error message `Lua scripting disabled`. `INFO` commands still include scripting statistics to prevent breaking any DevOps scripts, etc. Signed-off-by: Evan Wies --- README.md | 4 +++ src/Makefile | 17 +++++++++--- src/eval.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++ src/function_lua.c | 5 ++++ src/functions.c | 2 ++ src/lazyfree.c | 6 +++++ src/script_lua.c | 9 +++++++ src/server.h | 27 ++++++++++++++----- 8 files changed, 125 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 1a8ce1a4db..5f1231d0b3 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,10 @@ as libsystemd-dev on Debian/Ubuntu or systemd-devel on CentOS) and run: % make USE_SYSTEMD=yes +To build without Lua scripting (it is enabled by default), run: + + % make USE_LUA=no + To append a suffix to Valkey program names, use: % make PROG_SUFFIX="-alt" diff --git a/src/Makefile b/src/Makefile index ae2de1c626..5779c2caf0 100644 --- a/src/Makefile +++ b/src/Makefile @@ -31,7 +31,16 @@ endif ifneq ($(OPTIMIZATION),-O0) OPTIMIZATION+=-fno-omit-frame-pointer endif -DEPENDENCY_TARGETS=hiredis linenoise lua hdr_histogram fpconv + +# Lua enablement flags. Lua is enabled by default, +# but can be disabled with USE_LUA=no +ifneq ($(USE_LUA),no) + LUA_LIBS=../deps/lua/src/liblua.a + LUA_CFLAGS=-I../deps/lua/src -DUSE_LUA + LUA_TARGET=lua +endif + +DEPENDENCY_TARGETS=hiredis linenoise ${LUA_TARGET} hdr_histogram fpconv NODEPS:=clean distclean # Default settings @@ -248,7 +257,7 @@ ifdef OPENSSL_PREFIX endif # Include paths to dependencies -FINAL_CFLAGS+= -I../deps/hiredis -I../deps/linenoise -I../deps/lua/src -I../deps/hdr_histogram -I../deps/fpconv +FINAL_CFLAGS+= -I../deps/hiredis -I../deps/linenoise ${LUA_CFLAGS} -I../deps/hdr_histogram -I../deps/fpconv # Determine systemd support and/or build preference (defaulting to auto-detection) BUILD_WITH_SYSTEMD=no @@ -477,7 +486,7 @@ endif # valkey-server $(SERVER_NAME): $(ENGINE_SERVER_OBJ) - $(SERVER_LD) -o $@ $^ ../deps/hiredis/libhiredis.a ../deps/lua/src/liblua.a ../deps/hdr_histogram/libhdrhistogram.a ../deps/fpconv/libfpconv.a $(FINAL_LIBS) + $(SERVER_LD) -o $@ $^ ../deps/hiredis/libhiredis.a ${LUA_LIBS} ../deps/hdr_histogram/libhdrhistogram.a ../deps/fpconv/libfpconv.a $(FINAL_LIBS) # Valkey static library, used to compile against for unit testing $(ENGINE_LIB_NAME): $(ENGINE_SERVER_OBJ) @@ -485,7 +494,7 @@ $(ENGINE_LIB_NAME): $(ENGINE_SERVER_OBJ) # valkey-unit-tests $(ENGINE_UNIT_TESTS): $(ENGINE_TEST_OBJ) $(ENGINE_LIB_NAME) - $(SERVER_LD) -o $@ $^ ../deps/hiredis/libhiredis.a ../deps/lua/src/liblua.a ../deps/hdr_histogram/libhdrhistogram.a ../deps/fpconv/libfpconv.a $(FINAL_LIBS) + $(SERVER_LD) -o $@ $^ ../deps/hiredis/libhiredis.a ${LUA_LIBS} ../deps/hdr_histogram/libhdrhistogram.a ../deps/fpconv/libfpconv.a $(FINAL_LIBS) # valkey-sentinel $(ENGINE_SENTINEL_NAME): $(SERVER_NAME) diff --git a/src/eval.c b/src/eval.c index c6fd10073b..924c2a7b27 100644 --- a/src/eval.c +++ b/src/eval.c @@ -35,7 +35,11 @@ * 2. scriptingInit() - initServer() function from server.c invokes this to initialize LUA at startup. * It is also invoked between 2 eval invocations to reset Lua. */ + #include "server.h" + +#ifdef USE_LUA + #include "sha1.h" #include "rand.h" #include "cluster.h" @@ -1760,3 +1764,64 @@ void luaLdbLineHook(lua_State *lua, lua_Debug *ar) { rctx->start_time = getMonotonicUs(); } } + +#else /* USE_LUA is no */ + +/* These stubs are used when Lua is disabled at compile time. + * They typically do nothing and report 0. */ + +void scriptingInit(int setup) { + UNUSED(setup); +} + +int ldbPendingChildren(void) { + return 0; +} + +int ldbRemoveChild(pid_t pid) { + UNUSED(pid); + return 0; +} + +unsigned long evalMemory(void) { + return 0; +} + +unsigned long evalScriptsMemory(void) { + return 0; +} + +uint64_t evalGetCommandFlags(client *c, uint64_t cmd_flags) { + UNUSED(c); + /* Pass through the cmd_flags */ + return cmd_flags; +} + +unsigned long evalScriptsDictSize(void) { + return 0; +} + +void ldbKillForkedSessions(void) { +} + +void evalCommand(client *c) { + addReplyError(c, "Lua scripting disabled"); +} + +void evalRoCommand(client *c) { + addReplyError(c, "Lua scripting disabled"); +} + +void evalShaCommand(client *c) { + addReplyError(c, "Lua scripting disabled"); +} + +void evalShaRoCommand(client *c) { + addReplyError(c, "Lua scripting disabled"); +} + +void scriptCommand(client *c) { + addReplyError(c, "Lua scripting disabled"); +} + +#endif diff --git a/src/function_lua.c b/src/function_lua.c index fa9983bf7e..283751bf2e 100644 --- a/src/function_lua.c +++ b/src/function_lua.c @@ -40,6 +40,9 @@ */ #include "functions.h" + +#ifdef USE_LUA + #include "script_lua.h" #include #include @@ -507,3 +510,5 @@ int luaEngineInitEngine(void) { }; return functionsRegisterEngine(LUA_ENGINE_NAME, lua_engine); } + +#endif diff --git a/src/functions.c b/src/functions.c index a00fefb329..0cfc1bed8c 100644 --- a/src/functions.c +++ b/src/functions.c @@ -1114,9 +1114,11 @@ size_t functionsLibCtxFunctionsLen(functionsLibCtx *functions_ctx) { int functionsInit(void) { engines = dictCreate(&engineDictType); +#ifdef USE_LUA if (luaEngineInitEngine() != C_OK) { return C_ERR; } +#endif /* Must be initialized after engines initialization */ curr_functions_lib_ctx = functionsLibCtxCreate(); diff --git a/src/lazyfree.c b/src/lazyfree.c index 6176b43440..c25e0dc4f7 100644 --- a/src/lazyfree.c +++ b/src/lazyfree.c @@ -51,6 +51,9 @@ void lazyFreeErrors(void *args[]) { /* Release the lua_scripts dict. */ void lazyFreeLuaScripts(void *args[]) { +#ifndef USE_LUA + UNUSED(args); +#else dict *lua_scripts = args[0]; list *lua_scripts_lru_list = args[1]; lua_State *lua = args[2]; @@ -58,6 +61,7 @@ void lazyFreeLuaScripts(void *args[]) { freeLuaScriptsSync(lua_scripts, lua_scripts_lru_list, lua); atomic_fetch_sub_explicit(&lazyfree_objects, len, memory_order_relaxed); atomic_fetch_add_explicit(&lazyfreed_objects, len, memory_order_relaxed); +#endif } /* Release the functions ctx. */ @@ -222,6 +226,7 @@ void freeErrorsRadixTreeAsync(rax *errors) { } } +#ifdef USE_LUA /* Free lua_scripts dict and lru list, if the dict is huge enough, free them in async way. * Close lua interpreter, if there are a lot of lua scripts, close it in async way. */ void freeLuaScriptsAsync(dict *lua_scripts, list *lua_scripts_lru_list, lua_State *lua) { @@ -232,6 +237,7 @@ void freeLuaScriptsAsync(dict *lua_scripts, list *lua_scripts_lru_list, lua_Stat freeLuaScriptsSync(lua_scripts, lua_scripts_lru_list, lua); } } +#endif /* Free functions ctx, if the functions ctx contains enough functions, free it in async way. */ void freeFunctionsAsync(functionsLibCtx *functions_lib_ctx) { diff --git a/src/script_lua.c b/src/script_lua.c index 5093fa944f..1a852b12db 100644 --- a/src/script_lua.c +++ b/src/script_lua.c @@ -27,6 +27,8 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#if USE_LUA + #include "script_lua.h" #include "fpconv_dtoa.h" @@ -1780,3 +1782,10 @@ void luaCallFunction(scriptRunCtx *run_ctx, unsigned long luaMemory(lua_State *lua) { return lua_gc(lua, LUA_GCCOUNT, 0) * 1024LL; } + +#else + +/* We need some declaration to prevent compiler warnings */ +#include + +#endif diff --git a/src/server.h b/src/server.h index 0d8740d8d6..bb12412ffe 100644 --- a/src/server.h +++ b/src/server.h @@ -50,7 +50,11 @@ #include #include #include + +#ifdef USE_LUA #include +#endif + #include #ifdef HAVE_LIBSYSTEMD @@ -3635,31 +3639,42 @@ int redis_check_rdb_main(int argc, char **argv, FILE *fp); int redis_check_aof_main(int argc, char **argv); /* Scripting */ + void scriptingInit(int setup); int ldbRemoveChild(pid_t pid); void ldbKillForkedSessions(void); int ldbPendingChildren(void); + +unsigned long evalMemory(void); +unsigned long evalScriptsDictSize(void); +unsigned long evalScriptsMemory(void); +uint64_t evalGetCommandFlags(client *c, uint64_t orig_flags); + +void freeFunctionsAsync(functionsLibCtx *lib_ctx); +uint64_t fcallGetCommandFlags(client *c, uint64_t orig_flags); +int isInsideYieldingLongCommand(void); + +#ifdef USE_LUA +/* The functions above are cross-cutting are stubbed when !USE_LUA. + * The declarations below are only included when Lua scripting is enabled. */ void luaLdbLineHook(lua_State *lua, lua_Debug *ar); void freeLuaScriptsSync(dict *lua_scripts, list *lua_scripts_lru_list, lua_State *lua); void freeLuaScriptsAsync(dict *lua_scripts, list *lua_scripts_lru_list, lua_State *lua); -void freeFunctionsAsync(functionsLibCtx *lib_ctx); int ldbIsEnabled(void); void ldbLog(sds entry); void ldbLogRespReply(char *reply); void sha1hex(char *digest, char *script, size_t len); unsigned long evalMemory(void); dict *evalScriptsDict(void); -unsigned long evalScriptsDictSize(void); -unsigned long evalScriptsMemory(void); -uint64_t evalGetCommandFlags(client *c, uint64_t orig_flags); -uint64_t fcallGetCommandFlags(client *c, uint64_t orig_flags); -int isInsideYieldingLongCommand(void); typedef struct luaScript { uint64_t flags; robj *body; listNode *node; /* list node in lua_scripts_lru_list list. */ } luaScript; + +#endif + /* Cache of recently used small arguments to avoid malloc calls. */ #define LUA_CMD_OBJCACHE_SIZE 32 #define LUA_CMD_OBJCACHE_MAX_LEN 64