Skip to content

Commit

Permalink
Build without Lua scripting via USE_LUA (valkey-io#1204)
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
neomantra committed Nov 2, 2024
1 parent 96a7bb5 commit 84b5269
Show file tree
Hide file tree
Showing 8 changed files with 125 additions and 10 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
17 changes: 13 additions & 4 deletions src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -477,15 +486,15 @@ 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)
$(SERVER_AR) rcs $@ $^

# 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)
Expand Down
65 changes: 65 additions & 0 deletions src/eval.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
5 changes: 5 additions & 0 deletions src/function_lua.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@
*/

#include "functions.h"

#ifdef USE_LUA

#include "script_lua.h"
#include <lua.h>
#include <lauxlib.h>
Expand Down Expand Up @@ -507,3 +510,5 @@ int luaEngineInitEngine(void) {
};
return functionsRegisterEngine(LUA_ENGINE_NAME, lua_engine);
}

#endif
2 changes: 2 additions & 0 deletions src/functions.c
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
6 changes: 6 additions & 0 deletions src/lazyfree.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,17 @@ 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];
long long len = dictSize(lua_scripts);
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. */
Expand Down Expand Up @@ -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) {
Expand All @@ -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) {
Expand Down
9 changes: 9 additions & 0 deletions src/script_lua.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
* POSSIBILITY OF SUCH DAMAGE.
*/

#if USE_LUA

#include "script_lua.h"
#include "fpconv_dtoa.h"

Expand Down Expand Up @@ -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 <math.h>

#endif
27 changes: 21 additions & 6 deletions src/server.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,11 @@
#include <syslog.h>
#include <netinet/in.h>
#include <sys/socket.h>

#ifdef USE_LUA
#include <lua.h>
#endif

#include <signal.h>

#ifdef HAVE_LIBSYSTEMD
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 84b5269

Please sign in to comment.