Repository: valkey-io/valkey
File: src/lua/engine_lua.c (C)

Code before:
            .context = lua,
            .engineLazyEnvResetCallback = resetLuaContext,
        };
    } else {
        resetLuaContext(lua);
    }

    initializeLuaState(lua_engine_ctx, type);

    return callback;
}

static size_t luaEngineFunctionMemoryOverhead(ValkeyModuleCtx *module_ctx,
                                              compiledFunction *compiled_function) {
    /* The lua engine is implemented in the core, and not in a Valkey Module */
    serverAssert(module_ctx == NULL);

    return zmalloc_size(compiled_function->function) +
           (compiled_function->name ? zmalloc_size(compiled_function->name) : 0) +
           (compiled_function->desc ? zmalloc_size(compiled_function->desc) : 0) +
           zmalloc_size(compiled_function);
}

static void luaEngineFreeFunction(ValkeyModuleCtx *module_ctx,
                                  engineCtx *engine_ctx,
                                  subsystemType type,
                                  compiledFunction *compiled_function) {
    /* The lua engine is implemented in the core, and not in a Valkey Module */
    serverAssert(module_ctx == NULL);
    serverAssert(type == VMSE_EVAL || type == VMSE_FUNCTION);

    luaEngineCtx *lua_engine_ctx = engine_ctx;
    lua_State *lua = type == VMSE_EVAL ? lua_engine_ctx->eval_lua : lua_engine_ctx->function_lua;
    serverAssert(lua);

    luaFunction *script = (luaFunction *)compiled_function->function;
    if (lua == script->lua) {
        /* The lua context is still the same, which means that we're not
         * resetting the whole eval context, and therefore, we need to
         * delete the function from the lua context.
         */
        lua_unref(lua, script->function_ref);
    }
    zfree(script);

    if (compiled_function->name) {
        decrRefCount(compiled_function->name);
    }
    if (compiled_function->desc) {
        decrRefCount(compiled_function->desc);
    }

Review comment (bug):
There's a problem here. The `compiled_function->function` pointer points to a `struct luaFunctionCtx` when `VMSE_FUNCTION`, whereas in the `VMSE_EVAL` case, it points to a `struct luaFunction`.

We need to drop the `struct luaFunctionCtx` and use `struct luaFunction` for both subsystems. This will also fix the test failure.

Code after:
}

static size_t luaEngineFunctionMemoryOverhead(ValkeyModuleCtx *module_ctx,
                                              compiledFunction *compiled_function) {
    /* The lua engine is implemented in the core, and not in a Valkey Module */
    serverAssert(module_ctx == NULL);

    return zmalloc_size(compiled_function->function) +
           (compiled_function->name ? zmalloc_size(compiled_function->name) : 0) +
           (compiled_function->desc ? zmalloc_size(compiled_function->desc) : 0) +
           zmalloc_size(compiled_function);
}

static void luaEngineFreeFunction(ValkeyModuleCtx *module_ctx,
                                  engineCtx *engine_ctx,
                                  subsystemType type,
                                  compiledFunction *compiled_function) {
    /* The lua engine is implemented in the core, and not in a Valkey Module */
    serverAssert(module_ctx == NULL);
    serverAssert(type == VMSE_EVAL || type == VMSE_FUNCTION);

    luaEngineCtx *lua_engine_ctx = engine_ctx;
    lua_State *lua = type == VMSE_EVAL ? lua_engine_ctx->eval_lua : lua_engine_ctx->function_lua;
    serverAssert(lua);

    luaFunction *script = (luaFunction *)compiled_function->function;
    if (lua == script->lua) {
        /* The lua context is still the same, which means that we're not
         * resetting the whole eval context, and therefore, we need to
         * delete the function from the lua context.
         */
        lua_unref(lua, script->function_ref);
    }
    zfree(script);

    if (compiled_function->name) {
        decrRefCount(compiled_function->name);
    }
    if (compiled_function->desc) {
        decrRefCount(compiled_function->desc);
    }
    zfree(compiled_function);
}

int luaEngineInitEngine(void) {
    ldbInit();

    engineMethods methods = {
        .version = VALKEYMODULE_SCRIPTING_ENGINE_ABI_VERSION,
        .compile_code = luaEngineCompileCode,
        .free_function = luaEngineFreeFunction,