From 9318c2a46bfec91e6212bd7d46e74998c78dd0c8 Mon Sep 17 00:00:00 2001 From: xiaobiaozhao Date: Sat, 10 Oct 2026 17:18:27 +0800 Subject: [PATCH] bugfix: server_rewrite_by_lua* used the global VM when lua_code_cache off. ngx_http_lua_server_rewrite_handler() fetched the Lua VM before the request context was created. With "lua_code_cache off", create_ctx() builds a fresh per-request VM in ctx->vm_state, so fetching the VM too early always returned the persistent global VM. That defeated per-request code caching, reused global coroutine threads, and caused a VM mismatch on yield/resume which aborted requests with "attempt to index field 'ctx' (a nil value)". Fetch the VM after create_ctx() and pass ctx, mirroring the rewrite phase handler. Also reset server_rewrite_src_ref to LUA_REFNIL when the code cache is disabled so inline/file chunks are recompiled per request. --- src/ngx_http_lua_server_rewriteby.c | 18 +++++- t/167-server-rewrite.t | 85 +++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+), 1 deletion(-) diff --git a/src/ngx_http_lua_server_rewriteby.c b/src/ngx_http_lua_server_rewriteby.c index d012a8e341..1e261ac223 100644 --- a/src/ngx_http_lua_server_rewriteby.c +++ b/src/ngx_http_lua_server_rewriteby.c @@ -39,7 +39,6 @@ ngx_http_lua_server_rewrite_handler(ngx_http_request_t *r) lscf = ngx_http_get_module_srv_conf(r, ngx_http_lua_module); llcf = ngx_http_get_module_loc_conf(r, ngx_http_lua_module); - L = ngx_http_lua_get_lua_vm(r, NULL); if (lscf->srv.server_rewrite_handler == NULL) { dd("no rewrite handler found"); @@ -57,6 +56,10 @@ ngx_http_lua_server_rewrite_handler(ngx_http_request_t *r) } } + /* must be fetched after create_ctx: with "lua_code_cache off" the + * per-request VM in ctx->vm_state does not exist until then */ + L = ngx_http_lua_get_lua_vm(r, ctx); + dd("entered? %d", (int) ctx->entered_server_rewrite_phase); if (ctx->entered_server_rewrite_phase) { @@ -133,9 +136,15 @@ ngx_http_lua_server_rewrite_handler_inline(ngx_http_request_t *r, ngx_http_lua_srv_conf_t *lscf, lua_State *L) { ngx_int_t rc; + ngx_http_lua_loc_conf_t *llcf; dd("server_rewrite by lua inline"); + llcf = ngx_http_get_module_loc_conf(r, ngx_http_lua_module); + + if (!llcf->enable_code_cache) { + lscf->srv.server_rewrite_src_ref = LUA_REFNIL; + } /* load Lua inline script (w/ cache) sp = 1 */ rc = ngx_http_lua_cache_loadbuffer(r->connection->log, L, @@ -160,6 +169,7 @@ ngx_http_lua_server_rewrite_handler_file(ngx_http_request_t *r, ngx_int_t rc; u_char *script_path; ngx_str_t eval_src; + ngx_http_lua_loc_conf_t *llcf; if (ngx_http_complex_value(r, &lscf->srv.server_rewrite_src, @@ -175,6 +185,12 @@ ngx_http_lua_server_rewrite_handler_file(ngx_http_request_t *r, return NGX_ERROR; } + llcf = ngx_http_get_module_loc_conf(r, ngx_http_lua_module); + + if (!llcf->enable_code_cache) { + lscf->srv.server_rewrite_src_ref = LUA_REFNIL; + } + /* load Lua script file (w/ cache) sp = 1 */ rc = ngx_http_lua_cache_loadfile(r->connection->log, L, script_path, &lscf->srv.server_rewrite_src_ref, diff --git a/t/167-server-rewrite.t b/t/167-server-rewrite.t index 33a30f3842..101ebd3ba7 100644 --- a/t/167-server-rewrite.t +++ b/t/167-server-rewrite.t @@ -489,3 +489,88 @@ GET /lua failed to load inlined Lua code: server_rewrite_by_lua(nginx.conf:39):2: unexpected symbol near ''for end'' --- no_error_log no_such_error + + + +=== TEST 21: server_rewrite_by_lua_file honors lua_code_cache off +--- config + lua_code_cache off; + + server_rewrite_by_lua_file html/test.lua; + + location /lua { + content_by_lua_block { + ngx.say(ngx.ctx.a) + } + } + location /update { + content_by_lua ' + local f = assert(io.open("$TEST_NGINX_SERVER_ROOT/html/test.lua", "w")) + f:write("ngx.ctx.a = 101") + f:close() + ngx.say("updated") + '; + } + location /main { + echo_location /lua; + echo_location /update; + echo_location /lua; + } +--- user_files +>>> test.lua +ngx.ctx.a = 32 +--- request +GET /main +--- response_body +32 +updated +101 +--- no_error_log +[error] + + + +=== TEST 22: server_rewrite_by_lua_block can yield when lua_code_cache is off +--- config + lua_code_cache off; + + server_rewrite_by_lua_block { + ngx.sleep(0.001) + ngx.ctx.a = "resumed" + } + + location /lua { + content_by_lua_block { + ngx.say(ngx.ctx.a) + } + } +--- request +GET /lua +--- response_body +resumed +--- no_error_log +[error] + + + +=== TEST 23: server_rewrite_by_lua_file can yield when lua_code_cache is off +--- config + lua_code_cache off; + + server_rewrite_by_lua_file html/sleep.lua; + + location /lua { + content_by_lua_block { + ngx.say(ngx.ctx.a) + } + } +--- user_files +>>> sleep.lua +ngx.sleep(0.001) +ngx.ctx.a = "resumed from file" +--- request +GET /lua +--- response_body +resumed from file +--- no_error_log +[error]