diff --git a/.travis.yml b/.travis.yml index f51ad0ce27..01a2d8fb82 100644 --- a/.travis.yml +++ b/.travis.yml @@ -72,7 +72,7 @@ install: - git clone https://github.com/openresty/no-pool-nginx.git ../no-pool-nginx - git clone https://github.com/openresty/openresty-devel-utils.git - git clone https://github.com/openresty/mockeagain.git - - git clone https://github.com/openresty/lua-cjson.git + - git clone -b arm64 https://github.com/spacewander/lua-cjson.git lua-cjson - git clone https://github.com/openresty/lua-upstream-nginx-module.git ../lua-upstream-nginx-module - git clone https://github.com/openresty/echo-nginx-module.git ../echo-nginx-module - git clone https://github.com/openresty/nginx-eval-module.git ../nginx-eval-module @@ -85,11 +85,11 @@ install: - git clone https://github.com/openresty/rds-json-nginx-module.git ../rds-json-nginx-module - git clone https://github.com/openresty/srcache-nginx-module.git ../srcache-nginx-module - git clone https://github.com/openresty/redis2-nginx-module.git ../redis2-nginx-module - - git clone https://github.com/openresty/lua-resty-core.git ../lua-resty-core + - git clone -b arm64 https://github.com/spacewander/lua-resty-core.git ../lua-resty-core - git clone https://github.com/openresty/lua-resty-lrucache.git ../lua-resty-lrucache - git clone https://github.com/openresty/lua-resty-mysql.git ../lua-resty-mysql - - git clone https://github.com/openresty/stream-lua-nginx-module.git ../stream-lua-nginx-module - - git clone -b v2.1-agentzh https://github.com/openresty/luajit2.git + - git clone -b arm64 https://github.com/spacewander/stream-lua-nginx-module.git ../stream-lua-nginx-module + - git clone -b exdata https://github.com/spacewander/luajit2.git luajit2 before_script: - mysql -uroot -e 'create database ngx_test; grant all on ngx_test.* to "ngx_test"@"%" identified by "ngx_test"; flush privileges;' diff --git a/src/ngx_http_lua_accessby.c b/src/ngx_http_lua_accessby.c index 56bf0fa0ad..f587806336 100644 --- a/src/ngx_http_lua_accessby.c +++ b/src/ngx_http_lua_accessby.c @@ -261,9 +261,11 @@ ngx_http_lua_access_by_chunk(lua_State *L, ngx_http_request_t *r) /* move code closure to new coroutine */ lua_xmove(L, co, 1); +#ifndef OPENRESTY_LUAJIT /* set closure's env table to new coroutine's globals table */ ngx_http_lua_get_globals_table(co); lua_setfenv(co, -2); +#endif /* save nginx request in coroutine globals table */ ngx_http_lua_set_req(co, r); diff --git a/src/ngx_http_lua_balancer.c b/src/ngx_http_lua_balancer.c index fdf2af31a7..3ecd592917 100644 --- a/src/ngx_http_lua_balancer.c +++ b/src/ngx_http_lua_balancer.c @@ -362,6 +362,8 @@ ngx_http_lua_balancer_by_chunk(lua_State *L, ngx_http_request_t *r) /* init nginx context in Lua VM */ ngx_http_lua_set_req(L, r); + +#ifndef OPENRESTY_LUAJIT ngx_http_lua_create_new_globals_table(L, 0 /* narr */, 1 /* nrec */); /* {{{ make new env inheriting main thread's globals table */ @@ -372,6 +374,7 @@ ngx_http_lua_balancer_by_chunk(lua_State *L, ngx_http_request_t *r) /* }}} */ lua_setfenv(L, -2); /* set new running env for the code closure */ +#endif /* OPENRESTY_LUAJIT */ lua_pushcfunction(L, ngx_http_lua_traceback); lua_insert(L, 1); /* put it under chunk and args */ diff --git a/src/ngx_http_lua_bodyfilterby.c b/src/ngx_http_lua_bodyfilterby.c index 2b3c38f7ce..f3af14c164 100644 --- a/src/ngx_http_lua_bodyfilterby.c +++ b/src/ngx_http_lua_bodyfilterby.c @@ -32,10 +32,6 @@ static void ngx_http_lua_body_filter_by_lua_env(lua_State *L, static ngx_http_output_body_filter_pt ngx_http_next_body_filter; -/* key for the ngx_chain_t *in pointer in the Lua thread */ -#define ngx_http_lua_chain_key "__ngx_cl" - - /** * Set environment table for the given code closure. * @@ -51,12 +47,14 @@ static void ngx_http_lua_body_filter_by_lua_env(lua_State *L, ngx_http_request_t *r, ngx_chain_t *in) { - /* set nginx request pointer to current lua thread's globals table */ + ngx_http_lua_main_conf_t *lmcf; + ngx_http_lua_set_req(L, r); - lua_pushlightuserdata(L, in); - lua_setglobal(L, ngx_http_lua_chain_key); + lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module); + lmcf->body_filter_chain = in; +#ifndef OPENRESTY_LUAJIT /** * we want to create empty environment for current script * @@ -79,6 +77,7 @@ ngx_http_lua_body_filter_by_lua_env(lua_State *L, ngx_http_request_t *r, /* }}} */ lua_setfenv(L, -2); /* set new running env for the code closure */ +#endif /* OPENRESTY_LUAJIT */ } @@ -236,8 +235,8 @@ ngx_http_lua_body_filter(ngx_http_request_t *r, ngx_chain_t *in) ngx_int_t rc; uint16_t old_context; ngx_http_cleanup_t *cln; - lua_State *L; ngx_chain_t *out; + ngx_http_lua_main_conf_t *lmcf; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "lua body filter for user lua code, uri \"%V\"", &r->uri); @@ -299,11 +298,8 @@ ngx_http_lua_body_filter(ngx_http_request_t *r, ngx_chain_t *in) return NGX_ERROR; } - L = ngx_http_lua_get_lua_vm(r, ctx); - - lua_getglobal(L, ngx_http_lua_chain_key); - out = lua_touserdata(L, -1); - lua_pop(L, 1); + lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module); + out = lmcf->body_filter_chain; if (in == out) { return ngx_http_next_body_filter(r, in); @@ -345,7 +341,7 @@ ngx_http_lua_body_filter_init(void) int -ngx_http_lua_body_filter_param_get(lua_State *L) +ngx_http_lua_body_filter_param_get(lua_State *L, ngx_http_request_t *r) { u_char *data, *p; size_t size; @@ -354,6 +350,8 @@ ngx_http_lua_body_filter_param_get(lua_State *L) int idx; ngx_chain_t *in; + ngx_http_lua_main_conf_t *lmcf; + idx = luaL_checkint(L, 2); dd("index: %d", idx); @@ -363,8 +361,8 @@ ngx_http_lua_body_filter_param_get(lua_State *L) return 1; } - lua_getglobal(L, ngx_http_lua_chain_key); - in = lua_touserdata(L, -1); + lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module); + in = lmcf->body_filter_chain; if (idx == 2) { /* asking for the eof argument */ @@ -442,6 +440,8 @@ ngx_http_lua_body_filter_param_set(lua_State *L, ngx_http_request_t *r, ngx_chain_t *cl; ngx_chain_t *in; + ngx_http_lua_main_conf_t *lmcf; + idx = luaL_checkint(L, 2); dd("index: %d", idx); @@ -450,13 +450,13 @@ ngx_http_lua_body_filter_param_set(lua_State *L, ngx_http_request_t *r, return luaL_error(L, "bad index: %d", idx); } + lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module); + if (idx == 2) { /* overwriting the eof flag */ last = lua_toboolean(L, 3); - lua_getglobal(L, ngx_http_lua_chain_key); - in = lua_touserdata(L, -1); - lua_pop(L, 1); + in = lmcf->body_filter_chain; if (last) { ctx->seen_last_in_filter = 1; @@ -521,9 +521,7 @@ ngx_http_lua_body_filter_param_set(lua_State *L, ngx_http_request_t *r, case LUA_TNIL: /* discard the buffers */ - lua_getglobal(L, ngx_http_lua_chain_key); /* key val */ - in = lua_touserdata(L, -1); - lua_pop(L, 1); + in = lmcf->body_filter_chain; last = 0; @@ -557,9 +555,7 @@ ngx_http_lua_body_filter_param_set(lua_State *L, ngx_http_request_t *r, lua_typename(L, type)); } - lua_getglobal(L, ngx_http_lua_chain_key); - in = lua_touserdata(L, -1); - lua_pop(L, 1); + in = lmcf->body_filter_chain; last = 0; @@ -625,8 +621,8 @@ ngx_http_lua_body_filter_param_set(lua_State *L, ngx_http_request_t *r, } } - lua_pushlightuserdata(L, cl); - lua_setglobal(L, ngx_http_lua_chain_key); + lmcf->body_filter_chain = cl; + return 0; } diff --git a/src/ngx_http_lua_bodyfilterby.h b/src/ngx_http_lua_bodyfilterby.h index 6a4b306d64..b108202faa 100644 --- a/src/ngx_http_lua_bodyfilterby.h +++ b/src/ngx_http_lua_bodyfilterby.h @@ -21,7 +21,7 @@ ngx_int_t ngx_http_lua_body_filter_inline(ngx_http_request_t *r, ngx_chain_t *in); ngx_int_t ngx_http_lua_body_filter_file(ngx_http_request_t *r, ngx_chain_t *in); -int ngx_http_lua_body_filter_param_get(lua_State *L); +int ngx_http_lua_body_filter_param_get(lua_State *L, ngx_http_request_t *r); int ngx_http_lua_body_filter_param_set(lua_State *L, ngx_http_request_t *r, ngx_http_lua_ctx_t *ctx); diff --git a/src/ngx_http_lua_cache.c b/src/ngx_http_lua_cache.c index 5ea3069246..3e0f209f65 100644 --- a/src/ngx_http_lua_cache.c +++ b/src/ngx_http_lua_cache.c @@ -35,11 +35,14 @@ static ngx_int_t ngx_http_lua_cache_load_code(ngx_log_t *log, lua_State *L, const char *key) { +#ifndef OPENRESTY_LUAJIT int rc; u_char *err; +#endif /* get code cache table */ - lua_pushlightuserdata(L, &ngx_http_lua_code_cache_key); + lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( + code_cache_key)); lua_rawget(L, LUA_REGISTRYINDEX); /* sp++ */ dd("Code cache table to load: %p", lua_topointer(L, -1)); @@ -52,6 +55,10 @@ ngx_http_lua_cache_load_code(ngx_log_t *log, lua_State *L, lua_getfield(L, -1, key); /* sp++ */ if (lua_isfunction(L, -1)) { +#ifdef OPENRESTY_LUAJIT + lua_remove(L, -2); /* sp-- */ + return NGX_OK; +#else /* call closure factory to gen new closure */ rc = lua_pcall(L, 0, 1, 0); if (rc == 0) { @@ -73,6 +80,7 @@ ngx_http_lua_cache_load_code(ngx_log_t *log, lua_State *L, key, err); lua_pop(L, 2); return NGX_ERROR; +#endif /* OPENRESTY_LUAJIT */ } dd("Value associated with given key in code cache table is not code " @@ -102,10 +110,13 @@ ngx_http_lua_cache_load_code(ngx_log_t *log, lua_State *L, static ngx_int_t ngx_http_lua_cache_store_code(lua_State *L, const char *key) { +#ifndef OPENRESTY_LUAJIT int rc; +#endif /* get code cache table */ - lua_pushlightuserdata(L, &ngx_http_lua_code_cache_key); + lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( + code_cache_key)); lua_rawget(L, LUA_REGISTRYINDEX); dd("Code cache table to store: %p", lua_topointer(L, -1)); @@ -121,12 +132,14 @@ ngx_http_lua_cache_store_code(lua_State *L, const char *key) /* remove cache table, leave closure factory at top of stack */ lua_pop(L, 1); /* closure */ +#ifndef OPENRESTY_LUAJIT /* call closure factory to generate new closure */ rc = lua_pcall(L, 0, 1, 0); if (rc != 0) { dd("Error: failed to call closure factory!!"); return NGX_ERROR; } +#endif return NGX_OK; } diff --git a/src/ngx_http_lua_clfactory.c b/src/ngx_http_lua_clfactory.c index 041f0466e6..754ed8d2f1 100644 --- a/src/ngx_http_lua_clfactory.c +++ b/src/ngx_http_lua_clfactory.c @@ -15,11 +15,13 @@ #include "ngx_http_lua_clfactory.h" +#ifndef OPENRESTY_LUAJIT #define CLFACTORY_BEGIN_CODE "return function() " #define CLFACTORY_BEGIN_SIZE (sizeof(CLFACTORY_BEGIN_CODE) - 1) #define CLFACTORY_END_CODE "\nend" #define CLFACTORY_END_SIZE (sizeof(CLFACTORY_END_CODE) - 1) +#endif /* @@ -59,6 +61,7 @@ * length(Instruction) = 4 or 8 * little endian or big endian */ +#ifndef OPENRESTY_LUAJIT #define LUA_LITTLE_ENDIAN_4BYTES_CODE \ "\x24\x00\x00\x00\x1e\x00\x00\x01\x1e\x00\x80\x00" #define LUA_LITTLE_ENDIAN_8BYTES_CODE \ @@ -75,6 +78,7 @@ #define LUA_BIG_ENDIAN_8BYTES_CODE_LEN (8 + 8 + 8) #define LUAC_HEADERSIZE 12 #define LUAC_VERSION 0x51 +#endif /* OPENRESTY_LUAJIT */ /* @@ -147,6 +151,7 @@ * --------------------- */ +#ifndef OPENRESTY_LUAJIT #define POS_SOURCE_STR_LEN LUAC_HEADERSIZE #define POS_START_LINE (POS_SOURCE_STR_LEN + sizeof(size_t)) #define POS_LAST_LINE (POS_START_LINE + sizeof(int)) @@ -160,6 +165,7 @@ (POS_BYTECODE + LUA_LITTLE_ENDIAN_8BYTES_CODE_LEN \ + sizeof(int) + sizeof(int)) #define MAX_END_CODE_SIZE (sizeof(int) + sizeof(int) + sizeof(int)) +#endif /* OPENRESTY_LUAJIT */ /* * taken from chaoslawful: @@ -225,6 +231,7 @@ /* bytecode for luajit 2.0 */ +#ifndef OPENRESTY_LUAJIT #define LJ20_LITTLE_ENDIAN_CODE_STRIPPED \ "\x14\x03\x00\x01\x00\x01\x00\x03" \ "\x31\x00\x00\x00\x30\x00\x00\x80\x48\x00\x02\x00" \ @@ -275,6 +282,7 @@ #define LJ21_BCDUMP_VERSION 2 #define LJ20_BCDUMP_VERSION 1 #define LJ_SIGNATURE "\x1b\x4c\x4a" +#endif /* OPENRESTY_LUAJIT */ typedef enum { @@ -292,10 +300,11 @@ enum { typedef struct { ngx_http_lua_clfactory_file_type_e file_type; - int sent_begin; - int sent_end; int extraline; FILE *f; +#ifndef OPENRESTY_LUAJIT + int sent_begin; + int sent_end; size_t begin_code_len; size_t end_code_len; size_t rest_len; @@ -307,13 +316,16 @@ typedef struct { char *ptr; char str[MAX_END_CODE_SIZE]; } end_code; +#endif /* OPENRESTY_LUAJIT */ char buff[NGX_LUA_READER_BUFSIZE]; } ngx_http_lua_clfactory_file_ctx_t; typedef struct { +#ifndef OPENRESTY_LUAJIT int sent_begin; int sent_end; +#endif const char *s; size_t size; } ngx_http_lua_clfactory_buffer_ctx_t; @@ -325,9 +337,12 @@ static int ngx_http_lua_clfactory_errfile(lua_State *L, const char *what, int fname_index); static const char *ngx_http_lua_clfactory_getS(lua_State *L, void *ud, size_t *size); +#ifndef OPENRESTY_LUAJIT static long ngx_http_lua_clfactory_file_size(FILE *f); +#endif +#ifndef OPENRESTY_LUAJIT int ngx_http_lua_clfactory_bytecode_prepare(lua_State *L, ngx_http_lua_clfactory_file_ctx_t *lf, int fname_index) @@ -593,6 +608,7 @@ ngx_http_lua_clfactory_bytecode_prepare(lua_State *L, return LUA_ERRFILE; } +#endif /* OPENRESTY_LUAJIT */ ngx_int_t @@ -612,10 +628,12 @@ ngx_http_lua_clfactory_loadfile(lua_State *L, const char *filename) lf.extraline = 0; lf.file_type = NGX_LUA_TEXT_FILE; +#ifndef OPENRESTY_LUAJIT lf.begin_code.ptr = CLFACTORY_BEGIN_CODE; lf.begin_code_len = CLFACTORY_BEGIN_SIZE; lf.end_code.ptr = CLFACTORY_END_CODE; lf.end_code_len = CLFACTORY_END_SIZE; +#endif lua_pushfstring(L, "@%s", filename); @@ -683,20 +701,27 @@ ngx_http_lua_clfactory_loadfile(lua_State *L, const char *filename) /* skip eventual `#!...' */ } +#ifndef OPENRESTY_LUAJIT status = ngx_http_lua_clfactory_bytecode_prepare(L, &lf, fname_index); if (status != 0) { return status; } +#endif lf.extraline = 0; } +#ifndef OPENRESTY_LUAJIT if (lf.file_type == NGX_LUA_TEXT_FILE) { ungetc(c, lf.f); } lf.sent_begin = lf.sent_end = 0; + +#else + ungetc(c, lf.f); +#endif status = lua_load(L, ngx_http_lua_clfactory_getF, &lf, lua_tostring(L, -1)); @@ -725,8 +750,10 @@ ngx_http_lua_clfactory_loadbuffer(lua_State *L, const char *buff, ls.s = buff; ls.size = size; +#ifndef OPENRESTY_LUAJIT ls.sent_begin = 0; ls.sent_end = 0; +#endif return lua_load(L, ngx_http_lua_clfactory_getS, &ls, name); } @@ -735,7 +762,9 @@ ngx_http_lua_clfactory_loadbuffer(lua_State *L, const char *buff, static const char * ngx_http_lua_clfactory_getF(lua_State *L, void *ud, size_t *size) { +#ifndef OPENRESTY_LUAJIT char *buf; +#endif size_t num; ngx_http_lua_clfactory_file_ctx_t *lf; @@ -748,6 +777,7 @@ ngx_http_lua_clfactory_getF(lua_State *L, void *ud, size_t *size) return "\n"; } +#ifndef OPENRESTY_LUAJIT if (lf->sent_begin == 0) { lf->sent_begin = 1; *size = lf->begin_code_len; @@ -761,12 +791,14 @@ ngx_http_lua_clfactory_getF(lua_State *L, void *ud, size_t *size) return buf; } +#endif /* OPENRESTY_LUAJIT */ num = fread(lf->buff, 1, sizeof(lf->buff), lf->f); dd("fread returned %d", (int) num); if (num == 0) { +#ifndef OPENRESTY_LUAJIT if (lf->sent_end == 0) { lf->sent_end = 1; *size = lf->end_code_len; @@ -780,11 +812,13 @@ ngx_http_lua_clfactory_getF(lua_State *L, void *ud, size_t *size) return buf; } +#endif /* OPENRESTY_LUAJIT */ *size = 0; return NULL; } +#ifndef OPENRESTY_LUAJIT if (lf->file_type == NGX_LUA_BT_LJ) { /* skip the footer(\x00) in luajit */ @@ -800,6 +834,7 @@ ngx_http_lua_clfactory_getF(lua_State *L, void *ud, size_t *size) } } } +#endif /* OPENRESTY_LUAJIT */ *size = num; return lf->buff; @@ -833,19 +868,23 @@ ngx_http_lua_clfactory_getS(lua_State *L, void *ud, size_t *size) { ngx_http_lua_clfactory_buffer_ctx_t *ls = ud; +#ifndef OPENRESTY_LUAJIT if (ls->sent_begin == 0) { ls->sent_begin = 1; *size = CLFACTORY_BEGIN_SIZE; return CLFACTORY_BEGIN_CODE; } +#endif if (ls->size == 0) { +#ifndef OPENRESTY_LUAJIT if (ls->sent_end == 0) { ls->sent_end = 1; *size = CLFACTORY_END_SIZE; return CLFACTORY_END_CODE; } +#endif return NULL; } @@ -857,6 +896,7 @@ ngx_http_lua_clfactory_getS(lua_State *L, void *ud, size_t *size) } +#ifndef OPENRESTY_LUAJIT static long ngx_http_lua_clfactory_file_size(FILE *f) { @@ -882,6 +922,7 @@ ngx_http_lua_clfactory_file_size(FILE *f) return len; } +#endif /* OPENRESTY_LUAJIT */ /* vi:set ft=c ts=4 sw=4 et fdm=marker: */ diff --git a/src/ngx_http_lua_common.h b/src/ngx_http_lua_common.h index 4fcbc9ee26..5e6b26b36b 100644 --- a/src/ngx_http_lua_common.h +++ b/src/ngx_http_lua_common.h @@ -17,7 +17,7 @@ #include #include -#include +#include #include #include @@ -140,6 +140,10 @@ typedef struct { #endif +#define ngx_http_lua_lightudata_mask(ludata) \ + ((void *) ((uintptr_t) (&ngx_http_lua_##ludata) & ((1UL << 47) - 1))) + + typedef struct ngx_http_lua_main_conf_s ngx_http_lua_main_conf_t; typedef union ngx_http_lua_srv_conf_u ngx_http_lua_srv_conf_t; @@ -208,11 +212,30 @@ struct ngx_http_lua_main_conf_s { ngx_str_t init_worker_src; ngx_http_lua_balancer_peer_data_t *balancer_peer_data; - /* balancer_by_lua does not support yielding and + /* balancer_by_lua* does not support yielding and * there cannot be any conflicts among concurrent requests, * thus it is safe to store the peer data in the main conf. */ + ngx_chain_t *body_filter_chain; + /* body_filter_by_lua* does not support yielding/recursive + * calling and there cannot be any conflicts among + * concurrent requests, thus it is safe to store the + * chain data in the main conf. + */ + + ngx_http_variable_value_t *setby_args; + /* set_by_lua* does not support yielding and + * there cannot be any conflicts among concurrent requests, + * thus it is safe to store the args point in the main conf. + */ + + size_t setby_nargs; + /* set_by_lua* does not support yielding and + * there cannot be any conflicts among concurrent requests, + * thus it is safe to store the nargs in the main conf. + */ + ngx_uint_t shm_zones_inited; ngx_http_lua_sema_mm_t *sema_mm; diff --git a/src/ngx_http_lua_contentby.c b/src/ngx_http_lua_contentby.c index ecd6c0e591..274c9ad33f 100644 --- a/src/ngx_http_lua_contentby.c +++ b/src/ngx_http_lua_contentby.c @@ -63,9 +63,11 @@ ngx_http_lua_content_by_chunk(lua_State *L, ngx_http_request_t *r) /* move code closure to new coroutine */ lua_xmove(L, co, 1); +#ifndef OPENRESTY_LUAJIT /* set closure's env table to new coroutine's globals table */ ngx_http_lua_get_globals_table(co); lua_setfenv(co, -2); +#endif /* save nginx request in coroutine globals table */ ngx_http_lua_set_req(co, r); diff --git a/src/ngx_http_lua_control.c b/src/ngx_http_lua_control.c index 6ac2cbf88c..5cd1d64c8e 100644 --- a/src/ngx_http_lua_control.c +++ b/src/ngx_http_lua_control.c @@ -432,7 +432,8 @@ ngx_http_lua_on_abort(lua_State *L) ngx_http_lua_coroutine_create_helper(L, r, ctx, &coctx); - lua_pushlightuserdata(L, &ngx_http_lua_coroutines_key); + lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( + coroutines_key)); lua_rawget(L, LUA_REGISTRYINDEX); lua_pushvalue(L, -2); diff --git a/src/ngx_http_lua_coroutine.c b/src/ngx_http_lua_coroutine.c index b790814a2b..99a24235a3 100644 --- a/src/ngx_http_lua_coroutine.c +++ b/src/ngx_http_lua_coroutine.c @@ -104,11 +104,15 @@ ngx_http_lua_coroutine_create_helper(lua_State *L, ngx_http_request_t *r, coctx->co = co; coctx->co_status = NGX_HTTP_LUA_CO_SUSPENDED; +#ifdef OPENRESTY_LUAJIT + ngx_http_lua_set_req(co, r); +#else /* make new coroutine share globals of the parent coroutine. * NOTE: globals don't have to be separated! */ ngx_http_lua_get_globals_table(L); lua_xmove(L, co, 1); ngx_http_lua_set_globals_table(co); +#endif lua_xmove(vm, L, 1); /* move coroutine from main thread to L */ @@ -288,15 +292,27 @@ ngx_http_lua_inject_coroutine_api(ngx_log_t *log, lua_State *L) { const char buf[] = "local keys = {'create', 'yield', 'resume', 'status'}\n" +#ifdef OPENRESTY_LUAJIT + "local get_req = require 'thread.exdata'\n" +#else "local getfenv = getfenv\n" +#endif "for _, key in ipairs(keys) do\n" "local std = coroutine['_' .. key]\n" "local ours = coroutine['__' .. key]\n" "local raw_ctx = ngx._phase_ctx\n" "coroutine[key] = function (...)\n" +#ifdef OPENRESTY_LUAJIT + "local r = get_req()\n" +#else "local r = getfenv(0).__ngx_req\n" - "if r then\n" +#endif + "if r ~= nil then\n" +#ifdef OPENRESTY_LUAJIT + "local ctx = raw_ctx()\n" +#else "local ctx = raw_ctx(r)\n" +#endif /* ignore header and body filters */ "if ctx ~= 0x020 and ctx ~= 0x040 then\n" "return ours(...)\n" diff --git a/src/ngx_http_lua_headerfilterby.c b/src/ngx_http_lua_headerfilterby.c index b504530b90..a0acd4a114 100644 --- a/src/ngx_http_lua_headerfilterby.c +++ b/src/ngx_http_lua_headerfilterby.c @@ -42,9 +42,9 @@ static ngx_http_output_header_filter_pt ngx_http_next_header_filter; static void ngx_http_lua_header_filter_by_lua_env(lua_State *L, ngx_http_request_t *r) { - /* set nginx request pointer to current lua thread's globals table */ ngx_http_lua_set_req(L, r); +#ifndef OPENRESTY_LUAJIT /** * we want to create empty environment for current script * @@ -68,6 +68,7 @@ ngx_http_lua_header_filter_by_lua_env(lua_State *L, ngx_http_request_t *r) /* }}} */ lua_setfenv(L, -2); /* set new running env for the code closure */ +#endif /* OPENRESTY_LUAJIT */ } diff --git a/src/ngx_http_lua_headers.c b/src/ngx_http_lua_headers.c index b833577d14..0ff905b15d 100644 --- a/src/ngx_http_lua_headers.c +++ b/src/ngx_http_lua_headers.c @@ -442,7 +442,8 @@ ngx_http_lua_ngx_req_get_headers(lua_State *L) lua_createtable(L, 0, count); if (!raw) { - lua_pushlightuserdata(L, &ngx_http_lua_headers_metatable_key); + lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( + headers_metatable_key)); lua_rawget(L, LUA_REGISTRYINDEX); lua_setmetatable(L, -2); } @@ -566,7 +567,8 @@ ngx_http_lua_ngx_resp_get_headers(lua_State *L) lua_createtable(L, 0, count + 2); if (!raw) { - lua_pushlightuserdata(L, &ngx_http_lua_headers_metatable_key); + lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( + headers_metatable_key)); lua_rawget(L, LUA_REGISTRYINDEX); lua_setmetatable(L, -2); } @@ -1081,7 +1083,8 @@ ngx_http_lua_create_headers_metatable(ngx_log_t *log, lua_State *L) "local new_key = string.gsub(string.lower(key), '_', '-')\n" "if new_key ~= key then return tb[new_key] else return nil end"; - lua_pushlightuserdata(L, &ngx_http_lua_headers_metatable_key); + lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( + headers_metatable_key)); /* metatable for ngx.req.get_headers(_, true) and * ngx.resp.get_headers(_, true) */ diff --git a/src/ngx_http_lua_logby.c b/src/ngx_http_lua_logby.c index 0f1d2f35b3..32d1cba727 100644 --- a/src/ngx_http_lua_logby.c +++ b/src/ngx_http_lua_logby.c @@ -38,9 +38,9 @@ static ngx_int_t ngx_http_lua_log_by_chunk(lua_State *L, ngx_http_request_t *r); static void ngx_http_lua_log_by_lua_env(lua_State *L, ngx_http_request_t *r) { - /* set nginx request pointer to current lua thread's globals table */ ngx_http_lua_set_req(L, r); +#ifndef OPENRESTY_LUAJIT /** * we want to create empty environment for current script * @@ -64,6 +64,7 @@ ngx_http_lua_log_by_lua_env(lua_State *L, ngx_http_request_t *r) /* }}} */ lua_setfenv(L, -2); /* set new running env for the code closure */ +#endif /* OPENRESTY_LUAJIT */ } diff --git a/src/ngx_http_lua_ndk.c b/src/ngx_http_lua_ndk.c index 24b80b4d36..6344183723 100644 --- a/src/ngx_http_lua_ndk.c +++ b/src/ngx_http_lua_ndk.c @@ -186,6 +186,47 @@ ngx_http_lua_inject_ndk_api(lua_State *L) } +int +ngx_http_lua_ffi_ndk_lookup_directive(const u_char *var_data, + size_t var_len, ndk_set_var_value_pt *func) +{ + *func = ngx_http_lookup_ndk_set_var_directive((u_char *) var_data, var_len); + + if (*func == NULL) { + return NGX_ERROR; + } + + return NGX_OK; +} + + +int +ngx_http_lua_ffi_ndk_set_var_get(ngx_http_request_t *r, + ndk_set_var_value_pt func, const u_char *arg_data, size_t arg_len, + ngx_http_lua_ffi_str_t *value) +{ + ngx_int_t rc; + ngx_str_t res; + ngx_http_variable_value_t arg; + + ngx_memzero(&arg, sizeof(ngx_http_variable_value_t)); + arg.valid = 1; + + arg.data = (u_char *) arg_data; + arg.len = arg_len; + + rc = func(r, &res, &arg); + + if (rc != NGX_OK) { + return rc; + } + + value->data = res.data; + value->len = res.len; + return NGX_OK; +} + + #endif /* defined(NDK) && NDK */ /* vi:set ft=c ts=4 sw=4 et fdm=marker: */ diff --git a/src/ngx_http_lua_regex.c b/src/ngx_http_lua_regex.c index 5f74843400..8f3373b4d5 100644 --- a/src/ngx_http_lua_regex.c +++ b/src/ngx_http_lua_regex.c @@ -248,7 +248,8 @@ ngx_http_lua_ngx_re_match_helper(lua_State *L, int wantcaps) dd("server pool %p", lmcf->pool); - lua_pushlightuserdata(L, &ngx_http_lua_regex_cache_key); + lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( + regex_cache_key)); lua_rawget(L, LUA_REGISTRYINDEX); /* table */ lua_pushliteral(L, "m"); @@ -719,7 +720,8 @@ ngx_http_lua_ngx_re_gmatch(lua_State *L) dd("server pool %p", lmcf->pool); - lua_pushlightuserdata(L, &ngx_http_lua_regex_cache_key); + lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( + regex_cache_key)); lua_rawget(L, LUA_REGISTRYINDEX); /* table */ lua_pushliteral(L, "m"); @@ -1387,7 +1389,8 @@ ngx_http_lua_ngx_re_sub_helper(lua_State *L, unsigned global) dd("server pool %p", lmcf->pool); - lua_pushlightuserdata(L, &ngx_http_lua_regex_cache_key); + lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( + regex_cache_key)); lua_rawget(L, LUA_REGISTRYINDEX); /* table */ lua_pushliteral(L, "s"); diff --git a/src/ngx_http_lua_rewriteby.c b/src/ngx_http_lua_rewriteby.c index 1bbe87c9b0..08f7566904 100644 --- a/src/ngx_http_lua_rewriteby.c +++ b/src/ngx_http_lua_rewriteby.c @@ -261,9 +261,11 @@ ngx_http_lua_rewrite_by_chunk(lua_State *L, ngx_http_request_t *r) /* move code closure to new coroutine */ lua_xmove(L, co, 1); +#ifndef OPENRESTY_LUAJIT /* set closure's env table to new coroutine's globals table */ ngx_http_lua_get_globals_table(co); lua_setfenv(co, -2); +#endif /* save nginx request in coroutine globals table */ ngx_http_lua_set_req(co, r); diff --git a/src/ngx_http_lua_setby.c b/src/ngx_http_lua_setby.c index 2e8762a29d..d4288b50c2 100644 --- a/src/ngx_http_lua_setby.c +++ b/src/ngx_http_lua_setby.c @@ -30,13 +30,6 @@ static void ngx_http_lua_set_by_lua_env(lua_State *L, ngx_http_request_t *r, size_t nargs, ngx_http_variable_value_t *args); -/* keys in Lua thread for fetching args and nargs in set_by_lua* */ - -#define ngx_http_lua_nargs_key "__ngx_nargs" - -#define ngx_http_lua_args_key "__ngx_args" - - ngx_int_t ngx_http_lua_set_by_chunk(lua_State *L, ngx_http_request_t *r, ngx_str_t *val, ngx_http_variable_value_t *args, size_t nargs, ngx_str_t *script) @@ -134,23 +127,24 @@ ngx_http_lua_set_by_chunk(lua_State *L, ngx_http_request_t *r, ngx_str_t *val, int -ngx_http_lua_setby_param_get(lua_State *L) +ngx_http_lua_setby_param_get(lua_State *L, ngx_http_request_t *r) { int idx; int n; ngx_http_variable_value_t *v; + ngx_http_lua_main_conf_t *lmcf; idx = luaL_checkint(L, 2); idx--; - /* get number of args from globals */ - lua_getglobal(L, ngx_http_lua_nargs_key); - n = (int) lua_tointeger(L, -1); + lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module); - /* get args from globals */ - lua_getglobal(L, ngx_http_lua_args_key); - v = lua_touserdata(L, -1); + /* get number of args from lmcf */ + n = lmcf->setby_nargs; + + /* get args from lmcf */ + v = lmcf->setby_args; if (idx < 0 || idx > n - 1) { lua_pushnil(L); @@ -178,15 +172,16 @@ static void ngx_http_lua_set_by_lua_env(lua_State *L, ngx_http_request_t *r, size_t nargs, ngx_http_variable_value_t *args) { - /* set nginx request pointer to current lua thread's globals table */ + ngx_http_lua_main_conf_t *lmcf; + ngx_http_lua_set_req(L, r); - lua_pushinteger(L, nargs); - lua_setglobal(L, ngx_http_lua_nargs_key); + lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module); - lua_pushlightuserdata(L, args); - lua_setglobal(L, ngx_http_lua_args_key); + lmcf->setby_nargs = nargs; + lmcf->setby_args = args; +#ifndef OPENRESTY_LUAJIT /** * we want to create empty environment for current script * @@ -211,6 +206,7 @@ ngx_http_lua_set_by_lua_env(lua_State *L, ngx_http_request_t *r, size_t nargs, /* }}} */ lua_setfenv(L, -2); /* set new running env for the code closure */ +#endif } /* vi:set ft=c ts=4 sw=4 et fdm=marker: */ diff --git a/src/ngx_http_lua_setby.h b/src/ngx_http_lua_setby.h index da71753eaa..f43eef753e 100644 --- a/src/ngx_http_lua_setby.h +++ b/src/ngx_http_lua_setby.h @@ -7,7 +7,7 @@ ngx_int_t ngx_http_lua_set_by_chunk(lua_State *L, ngx_http_request_t *r, ngx_str_t *val, ngx_http_variable_value_t *args, size_t nargs, ngx_str_t *script); -int ngx_http_lua_setby_param_get(lua_State *L); +int ngx_http_lua_setby_param_get(lua_State *L, ngx_http_request_t *r); #endif /* _NGX_HTTP_LUA_SET_BY_H_INCLUDED_ */ diff --git a/src/ngx_http_lua_shdict.c b/src/ngx_http_lua_shdict.c index 5fb7930a87..b017bea658 100644 --- a/src/ngx_http_lua_shdict.c +++ b/src/ngx_http_lua_shdict.c @@ -325,6 +325,7 @@ ngx_http_lua_inject_shdict_api(ngx_http_lua_main_conf_t *lmcf, lua_State *L) ngx_http_lua_shdict_ctx_t *ctx; ngx_uint_t i; ngx_shm_zone_t **zone; + ngx_shm_zone_t **zone_udata; if (lmcf->shdict_zones != NULL) { lua_createtable(L, 0, lmcf->shdict_zones->nelts /* nrec */); @@ -396,7 +397,9 @@ ngx_http_lua_inject_shdict_api(ngx_http_lua_main_conf_t *lmcf, lua_State *L) lua_createtable(L, 1 /* narr */, 0 /* nrec */); /* table of zone[i] */ - lua_pushlightuserdata(L, zone[i]); /* shared mt key ud */ + zone_udata = lua_newuserdata(L, sizeof(ngx_shm_zone_t *)); + /* shared mt key ud */ + *zone_udata = zone[i]; lua_rawseti(L, -2, SHDICT_USERDATA_INDEX); /* {zone[i]} */ lua_pushvalue(L, -3); /* shared mt key ud mt */ lua_setmetatable(L, -2); /* shared mt key ud */ @@ -431,11 +434,17 @@ static ngx_inline ngx_shm_zone_t * ngx_http_lua_shdict_get_zone(lua_State *L, int index) { ngx_shm_zone_t *zone; + ngx_shm_zone_t **zone_udata; lua_rawgeti(L, index, SHDICT_USERDATA_INDEX); - zone = lua_touserdata(L, -1); + zone_udata = lua_touserdata(L, -1); lua_pop(L, 1); + if (zone_udata == NULL) { + return NULL; + } + + zone = *zone_udata; return zone; } @@ -2209,6 +2218,17 @@ ngx_http_lua_find_zone(u_char *name_data, size_t name_len) #ifndef NGX_LUA_NO_FFI_API +ngx_shm_zone_t * +ngx_http_lua_ffi_shdict_udata_to_zone(void *zone_udata) +{ + if (zone_udata == NULL) { + return NULL; + } + + return *(ngx_shm_zone_t **) zone_udata; +} + + int ngx_http_lua_ffi_shdict_store(ngx_shm_zone_t *zone, int op, u_char *key, size_t key_len, int value_type, u_char *str_value_buf, @@ -2225,10 +2245,6 @@ ngx_http_lua_ffi_shdict_store(ngx_shm_zone_t *zone, int op, u_char *key, ngx_http_lua_shdict_ctx_t *ctx; ngx_http_lua_shdict_node_t *sd; - if (zone == NULL) { - return NGX_ERROR; - } - dd("exptime: %ld", exptime); ctx = zone->data; @@ -2490,10 +2506,6 @@ ngx_http_lua_ffi_shdict_get(ngx_shm_zone_t *zone, u_char *key, ngx_http_lua_shdict_node_t *sd; ngx_str_t value; - if (zone == NULL) { - return NGX_ERROR; - } - *err = NULL; ctx = zone->data; @@ -2636,10 +2648,6 @@ ngx_http_lua_ffi_shdict_incr(ngx_shm_zone_t *zone, u_char *key, u_char *p; ngx_queue_t *queue, *q; - if (zone == NULL) { - return NGX_ERROR; - } - if (init_ttl > 0) { tp = ngx_timeofday(); } @@ -2915,10 +2923,6 @@ ngx_http_lua_ffi_shdict_get_ttl(ngx_shm_zone_t *zone, u_char *key, ngx_http_lua_shdict_ctx_t *ctx; ngx_http_lua_shdict_node_t *sd; - if (zone == NULL) { - return NGX_ERROR; - } - ctx = zone->data; hash = ngx_crc32_short(key, key_len); @@ -2959,10 +2963,6 @@ ngx_http_lua_ffi_shdict_set_expire(ngx_shm_zone_t *zone, u_char *key, ngx_http_lua_shdict_ctx_t *ctx; ngx_http_lua_shdict_node_t *sd; - if (zone == NULL) { - return NGX_ERROR; - } - if (exptime > 0) { tp = ngx_timeofday(); } diff --git a/src/ngx_http_lua_socket_tcp.c b/src/ngx_http_lua_socket_tcp.c index 0717c46d50..d3ccf730f6 100644 --- a/src/ngx_http_lua_socket_tcp.c +++ b/src/ngx_http_lua_socket_tcp.c @@ -234,7 +234,8 @@ ngx_http_lua_inject_socket_tcp_api(ngx_log_t *log, lua_State *L) lua_setfield(L, -2, "socket"); /* {{{req socket object metatable */ - lua_pushlightuserdata(L, &ngx_http_lua_req_socket_metatable_key); + lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( + req_socket_metatable_key)); lua_createtable(L, 0 /* narr */, 5 /* nrec */); lua_pushcfunction(L, ngx_http_lua_socket_tcp_receive); @@ -256,7 +257,8 @@ ngx_http_lua_inject_socket_tcp_api(ngx_log_t *log, lua_State *L) /* }}} */ /* {{{raw req socket object metatable */ - lua_pushlightuserdata(L, &ngx_http_lua_raw_req_socket_metatable_key); + lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( + raw_req_socket_metatable_key)); lua_createtable(L, 0 /* narr */, 6 /* nrec */); lua_pushcfunction(L, ngx_http_lua_socket_tcp_receive); @@ -281,7 +283,8 @@ ngx_http_lua_inject_socket_tcp_api(ngx_log_t *log, lua_State *L) /* }}} */ /* {{{tcp object metatable */ - lua_pushlightuserdata(L, &ngx_http_lua_tcp_socket_metatable_key); + lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( + tcp_socket_metatable_key)); lua_createtable(L, 0 /* narr */, 12 /* nrec */); lua_pushcfunction(L, ngx_http_lua_socket_tcp_connect); @@ -330,7 +333,8 @@ ngx_http_lua_inject_socket_tcp_api(ngx_log_t *log, lua_State *L) /* }}} */ /* {{{upstream userdata metatable */ - lua_pushlightuserdata(L, &ngx_http_lua_upstream_udata_metatable_key); + lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( + upstream_udata_metatable_key)); lua_createtable(L, 0 /* narr */, 1 /* nrec */); /* metatable */ lua_pushcfunction(L, ngx_http_lua_socket_tcp_upstream_destroy); lua_setfield(L, -2, "__gc"); @@ -338,7 +342,8 @@ ngx_http_lua_inject_socket_tcp_api(ngx_log_t *log, lua_State *L) /* }}} */ /* {{{downstream userdata metatable */ - lua_pushlightuserdata(L, &ngx_http_lua_downstream_udata_metatable_key); + lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( + downstream_udata_metatable_key)); lua_createtable(L, 0 /* narr */, 1 /* nrec */); /* metatable */ lua_pushcfunction(L, ngx_http_lua_socket_downstream_destroy); lua_setfield(L, -2, "__gc"); @@ -346,7 +351,8 @@ ngx_http_lua_inject_socket_tcp_api(ngx_log_t *log, lua_State *L) /* }}} */ /* {{{socket pool userdata metatable */ - lua_pushlightuserdata(L, &ngx_http_lua_pool_udata_metatable_key); + lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( + pool_udata_metatable_key)); lua_createtable(L, 0, 1); /* metatable */ lua_pushcfunction(L, ngx_http_lua_socket_shutdown_pool); lua_setfield(L, -2, "__gc"); @@ -354,7 +360,8 @@ ngx_http_lua_inject_socket_tcp_api(ngx_log_t *log, lua_State *L) /* }}} */ /* {{{socket compiled pattern userdata metatable */ - lua_pushlightuserdata(L, &ngx_http_lua_pattern_udata_metatable_key); + lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( + pattern_udata_metatable_key)); lua_createtable(L, 0 /* narr */, 1 /* nrec */); /* metatable */ lua_pushcfunction(L, ngx_http_lua_socket_cleanup_compiled_pattern); lua_setfield(L, -2, "__gc"); @@ -364,7 +371,8 @@ ngx_http_lua_inject_socket_tcp_api(ngx_log_t *log, lua_State *L) #if (NGX_HTTP_SSL) /* {{{ssl session userdata metatable */ - lua_pushlightuserdata(L, &ngx_http_lua_ssl_session_metatable_key); + lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( + ssl_session_metatable_key)); lua_createtable(L, 0 /* narr */, 1 /* nrec */); /* metatable */ lua_pushcfunction(L, ngx_http_lua_ssl_free_session); lua_setfield(L, -2, "__gc"); @@ -412,7 +420,8 @@ ngx_http_lua_socket_tcp(lua_State *L) | NGX_HTTP_LUA_CONTEXT_SSL_SESS_FETCH); lua_createtable(L, 5 /* narr */, 1 /* nrec */); - lua_pushlightuserdata(L, &ngx_http_lua_tcp_socket_metatable_key); + lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( + tcp_socket_metatable_key)); lua_rawget(L, LUA_REGISTRYINDEX); lua_setmetatable(L, -2); @@ -580,7 +589,8 @@ ngx_http_lua_socket_tcp_connect(lua_State *L) } #if 1 - lua_pushlightuserdata(L, &ngx_http_lua_upstream_udata_metatable_key); + lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( + upstream_udata_metatable_key)); lua_rawget(L, LUA_REGISTRYINDEX); lua_setmetatable(L, -2); #endif @@ -1646,7 +1656,8 @@ ngx_http_lua_ssl_handshake_retval_handler(ngx_http_request_t *r, "lua ssl save session: %p", ssl_session); /* set up the __gc metamethod */ - lua_pushlightuserdata(L, &ngx_http_lua_ssl_session_metatable_key); + lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( + ssl_session_metatable_key)); lua_rawget(L, LUA_REGISTRYINDEX); lua_setmetatable(L, -2); } @@ -3796,7 +3807,8 @@ ngx_http_lua_socket_tcp_receiveuntil(lua_State *L) return luaL_error(L, "no memory"); } - lua_pushlightuserdata(L, &ngx_http_lua_pattern_udata_metatable_key); + lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( + pattern_udata_metatable_key)); lua_rawget(L, LUA_REGISTRYINDEX); lua_setmetatable(L, -2); @@ -4451,10 +4463,12 @@ ngx_http_lua_req_socket(lua_State *L) lua_createtable(L, 2 /* narr */, 3 /* nrec */); /* the object */ if (raw) { - lua_pushlightuserdata(L, &ngx_http_lua_raw_req_socket_metatable_key); + lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( + raw_req_socket_metatable_key)); } else { - lua_pushlightuserdata(L, &ngx_http_lua_req_socket_metatable_key); + lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( + req_socket_metatable_key)); } lua_rawget(L, LUA_REGISTRYINDEX); @@ -4466,7 +4480,8 @@ ngx_http_lua_req_socket(lua_State *L) } #if 1 - lua_pushlightuserdata(L, &ngx_http_lua_downstream_udata_metatable_key); + lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( + downstream_udata_metatable_key)); lua_rawget(L, LUA_REGISTRYINDEX); lua_setmetatable(L, -2); #endif @@ -4617,7 +4632,8 @@ ngx_http_lua_socket_tcp_setkeepalive(lua_State *L) luaL_checktype(L, 1, LUA_TTABLE); - lua_pushlightuserdata(L, &ngx_http_lua_socket_pool_key); + lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( + socket_pool_key)); lua_rawget(L, LUA_REGISTRYINDEX); lua_rawgeti(L, 1, SOCKET_KEY_INDEX); @@ -4734,7 +4750,8 @@ ngx_http_lua_socket_tcp_setkeepalive(lua_State *L) return luaL_error(L, "no memory"); } - lua_pushlightuserdata(L, &ngx_http_lua_pool_udata_metatable_key); + lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( + pool_udata_metatable_key)); lua_rawget(L, LUA_REGISTRYINDEX); lua_setmetatable(L, -2); @@ -4886,7 +4903,8 @@ ngx_http_lua_get_keepalive_peer(ngx_http_request_t *r, lua_State *L, pc = &u->peer; - lua_pushlightuserdata(L, &ngx_http_lua_socket_pool_key); + lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( + socket_pool_key)); lua_rawget(L, LUA_REGISTRYINDEX); /* table */ lua_pushvalue(L, key_index); /* key */ lua_rawget(L, -2); @@ -5058,7 +5076,8 @@ ngx_http_lua_socket_free_pool(ngx_log_t *log, ngx_http_lua_socket_pool_t *spool) L = spool->lua_vm; - lua_pushlightuserdata(L, &ngx_http_lua_socket_pool_key); + lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( + socket_pool_key)); lua_rawget(L, LUA_REGISTRYINDEX); lua_pushstring(L, (char *) spool->key); lua_pushnil(L); @@ -5517,7 +5536,8 @@ ngx_http_lua_cleanup_conn_pools(lua_State *L) { ngx_http_lua_socket_pool_t *spool; - lua_pushlightuserdata(L, &ngx_http_lua_socket_pool_key); + lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( + socket_pool_key)); lua_rawget(L, LUA_REGISTRYINDEX); /* table */ lua_pushnil(L); /* first key */ diff --git a/src/ngx_http_lua_socket_udp.c b/src/ngx_http_lua_socket_udp.c index 8927f4118d..cbc32d63ec 100644 --- a/src/ngx_http_lua_socket_udp.c +++ b/src/ngx_http_lua_socket_udp.c @@ -81,7 +81,8 @@ ngx_http_lua_inject_socket_udp_api(ngx_log_t *log, lua_State *L) lua_setfield(L, -2, "udp"); /* ngx socket */ /* udp socket object metatable */ - lua_pushlightuserdata(L, &ngx_http_lua_socket_udp_metatable_key); + lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( + socket_udp_metatable_key)); lua_createtable(L, 0 /* narr */, 6 /* nrec */); lua_pushcfunction(L, ngx_http_lua_socket_udp_setpeername); @@ -105,7 +106,8 @@ ngx_http_lua_inject_socket_udp_api(ngx_log_t *log, lua_State *L) /* }}} */ /* udp socket object metatable */ - lua_pushlightuserdata(L, &ngx_http_lua_udp_udata_metatable_key); + lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( + udp_udata_metatable_key)); lua_createtable(L, 0 /* narr */, 1 /* nrec */); /* metatable */ lua_pushcfunction(L, ngx_http_lua_socket_udp_upstream_destroy); lua_setfield(L, -2, "__gc"); @@ -144,7 +146,8 @@ ngx_http_lua_socket_udp(lua_State *L) | NGX_HTTP_LUA_CONTEXT_SSL_CERT); lua_createtable(L, 3 /* narr */, 1 /* nrec */); - lua_pushlightuserdata(L, &ngx_http_lua_socket_udp_metatable_key); + lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( + socket_udp_metatable_key)); lua_rawget(L, LUA_REGISTRYINDEX); lua_setmetatable(L, -2); @@ -263,7 +266,8 @@ ngx_http_lua_socket_udp_setpeername(lua_State *L) } #if 1 - lua_pushlightuserdata(L, &ngx_http_lua_udp_udata_metatable_key); + lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( + udp_udata_metatable_key)); lua_rawget(L, LUA_REGISTRYINDEX); lua_setmetatable(L, -2); #endif diff --git a/src/ngx_http_lua_ssl_certby.c b/src/ngx_http_lua_ssl_certby.c index 453a5c78e4..622d0a5c1a 100644 --- a/src/ngx_http_lua_ssl_certby.c +++ b/src/ngx_http_lua_ssl_certby.c @@ -498,9 +498,11 @@ ngx_http_lua_ssl_cert_by_chunk(lua_State *L, ngx_http_request_t *r) /* move code closure to new coroutine */ lua_xmove(L, co, 1); +#ifndef OPENRESTY_LUAJIT /* set closure's env table to new coroutine's globals table */ ngx_http_lua_get_globals_table(co); lua_setfenv(co, -2); +#endif /* save nginx request in coroutine globals table */ ngx_http_lua_set_req(co, r); diff --git a/src/ngx_http_lua_ssl_session_fetchby.c b/src/ngx_http_lua_ssl_session_fetchby.c index 0b88a87ee8..303efb47aa 100644 --- a/src/ngx_http_lua_ssl_session_fetchby.c +++ b/src/ngx_http_lua_ssl_session_fetchby.c @@ -505,9 +505,11 @@ ngx_http_lua_ssl_sess_fetch_by_chunk(lua_State *L, ngx_http_request_t *r) /* move code closure to new coroutine */ lua_xmove(L, co, 1); +#ifndef OPENRESTY_LUAJIT /* set closure's env table to new coroutine's globals table */ ngx_http_lua_get_globals_table(co); lua_setfenv(co, -2); +#endif /* save nginx request in coroutine globals table */ ngx_http_lua_set_req(co, r); diff --git a/src/ngx_http_lua_ssl_session_storeby.c b/src/ngx_http_lua_ssl_session_storeby.c index 7609c39b6a..a02f729ced 100644 --- a/src/ngx_http_lua_ssl_session_storeby.c +++ b/src/ngx_http_lua_ssl_session_storeby.c @@ -380,6 +380,8 @@ ngx_http_lua_ssl_sess_store_by_chunk(lua_State *L, ngx_http_request_t *r) /* init nginx context in Lua VM */ ngx_http_lua_set_req(L, r); + +#ifndef OPENRESTY_LUAJIT ngx_http_lua_create_new_globals_table(L, 0 /* narr */, 1 /* nrec */); /* {{{ make new env inheriting main thread's globals table */ @@ -390,6 +392,7 @@ ngx_http_lua_ssl_sess_store_by_chunk(lua_State *L, ngx_http_request_t *r) /* }}} */ lua_setfenv(L, -2); /* set new running env for the code closure */ +#endif lua_pushcfunction(L, ngx_http_lua_traceback); lua_insert(L, 1); /* put it under chunk and args */ diff --git a/src/ngx_http_lua_timer.c b/src/ngx_http_lua_timer.c index 596b2f77e9..eb10a8fc36 100644 --- a/src/ngx_http_lua_timer.c +++ b/src/ngx_http_lua_timer.c @@ -220,6 +220,7 @@ ngx_http_lua_ngx_timer_helper(lua_State *L, int every) ngx_http_lua_probe_user_coroutine_create(r, L, co); +#ifndef OPENRESTY_LUAJIT lua_createtable(co, 0, 0); /* the new globals table */ /* co stack: global_tb */ @@ -232,6 +233,7 @@ ngx_http_lua_ngx_timer_helper(lua_State *L, int every) /* co stack: global_tb */ ngx_http_lua_set_globals_table(co); +#endif /* co stack: */ @@ -251,12 +253,15 @@ ngx_http_lua_ngx_timer_helper(lua_State *L, int every) /* L stack: time func [args] thread */ /* co stack: func */ +#ifndef OPENRESTY_LUAJIT ngx_http_lua_get_globals_table(co); lua_setfenv(co, -2); +#endif /* co stack: func */ - lua_pushlightuserdata(L, &ngx_http_lua_coroutines_key); + lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( + coroutines_key)); lua_rawget(L, LUA_REGISTRYINDEX); /* L stack: time func [args] thread coroutines */ @@ -358,7 +363,8 @@ ngx_http_lua_ngx_timer_helper(lua_State *L, int every) ngx_free(ev); } - lua_pushlightuserdata(L, &ngx_http_lua_coroutines_key); + lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( + coroutines_key)); lua_rawget(L, LUA_REGISTRYINDEX); luaL_unref(L, -1, co_ref); @@ -387,6 +393,7 @@ ngx_http_lua_timer_copy(ngx_http_lua_timer_ctx_t *old_tctx) co = lua_newthread(vm); +#ifndef OPENRESTY_LUAJIT lua_createtable(co, 0, 0); /* the new globals table */ /* co stack: global_tb */ @@ -399,6 +406,7 @@ ngx_http_lua_timer_copy(ngx_http_lua_timer_ctx_t *old_tctx) /* co stack: global_tb */ ngx_http_lua_set_globals_table(co); +#endif /* co stack: */ @@ -418,12 +426,15 @@ ngx_http_lua_timer_copy(ngx_http_lua_timer_ctx_t *old_tctx) /* L stack: func [args] thread */ /* co stack: func */ +#ifndef OPENRESTY_LUAJIT ngx_http_lua_get_globals_table(co); lua_setfenv(co, -2); +#endif /* co stack: func */ - lua_pushlightuserdata(L, &ngx_http_lua_coroutines_key); + lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( + coroutines_key)); lua_rawget(L, LUA_REGISTRYINDEX); /* L stack: func [args] thread coroutines */ @@ -512,7 +523,8 @@ ngx_http_lua_timer_copy(ngx_http_lua_timer_ctx_t *old_tctx) /* L stack: func [args] */ - lua_pushlightuserdata(L, &ngx_http_lua_coroutines_key); + lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( + coroutines_key)); lua_rawget(L, LUA_REGISTRYINDEX); luaL_unref(L, -1, co_ref); @@ -692,7 +704,8 @@ ngx_http_lua_timer_handler(ngx_event_t *ev) failed: if (tctx.co_ref && tctx.co) { - lua_pushlightuserdata(tctx.co, &ngx_http_lua_coroutines_key); + lua_pushlightuserdata(tctx.co, ngx_http_lua_lightudata_mask( + coroutines_key)); lua_rawget(tctx.co, LUA_REGISTRYINDEX); luaL_unref(tctx.co, -1, tctx.co_ref); lua_settop(tctx.co, 0); diff --git a/src/ngx_http_lua_uthread.c b/src/ngx_http_lua_uthread.c index 8195ec0f82..43517a049d 100644 --- a/src/ngx_http_lua_uthread.c +++ b/src/ngx_http_lua_uthread.c @@ -70,7 +70,8 @@ ngx_http_lua_uthread_spawn(lua_State *L) /* anchor the newly created coroutine into the Lua registry */ - lua_pushlightuserdata(L, &ngx_http_lua_coroutines_key); + lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( + coroutines_key)); lua_rawget(L, LUA_REGISTRYINDEX); lua_pushvalue(L, -2); coctx->co_ref = luaL_ref(L, -2); diff --git a/src/ngx_http_lua_util.c b/src/ngx_http_lua_util.c index f7a537ee96..12ef186bae 100644 --- a/src/ngx_http_lua_util.c +++ b/src/ngx_http_lua_util.c @@ -171,6 +171,7 @@ ngx_http_lua_set_path(ngx_cycle_t *cycle, lua_State *L, int tab_idx, } +#ifndef OPENRESTY_LUAJIT /** * Create new table and set _G field to itself. * @@ -185,6 +186,7 @@ ngx_http_lua_create_new_globals_table(lua_State *L, int narr, int nrec) lua_pushvalue(L, -1); lua_setfield(L, -2, "_G"); } +#endif /* OPENRESTY_LUAJIT */ static lua_State * @@ -313,11 +315,13 @@ ngx_http_lua_new_thread(ngx_http_request_t *r, lua_State *L, int *ref) base = lua_gettop(L); - lua_pushlightuserdata(L, &ngx_http_lua_coroutines_key); + lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( + coroutines_key)); lua_rawget(L, LUA_REGISTRYINDEX); co = lua_newthread(L); +#ifndef OPENRESTY_LUAJIT /* {{{ inherit coroutine's globals to main thread's globals table * for print() function will try to find tostring() in current * globals table. @@ -332,6 +336,7 @@ ngx_http_lua_new_thread(ngx_http_request_t *r, lua_State *L, int *ref) ngx_http_lua_set_globals_table(co); /* }}} */ +#endif /* OPENRESTY_LUAJIT */ *ref = luaL_ref(L, -2); @@ -356,7 +361,8 @@ ngx_http_lua_del_thread(ngx_http_request_t *r, lua_State *L, ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "lua deleting light thread"); - lua_pushlightuserdata(L, &ngx_http_lua_coroutines_key); + lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( + coroutines_key)); lua_rawget(L, LUA_REGISTRYINDEX); ngx_http_lua_probe_thread_delete(r, coctx->co, ctx); @@ -657,7 +663,8 @@ ngx_http_lua_init_registry(lua_State *L, ngx_log_t *log) /* {{{ register a table to anchor lua coroutines reliably: * {([int]ref) = [cort]} */ - lua_pushlightuserdata(L, &ngx_http_lua_coroutines_key); + lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( + coroutines_key)); lua_createtable(L, 0, 32 /* nrec */); lua_rawset(L, LUA_REGISTRYINDEX); /* }}} */ @@ -668,20 +675,23 @@ ngx_http_lua_init_registry(lua_State *L, ngx_log_t *log) lua_rawset(L, LUA_REGISTRYINDEX); /* create the registry entry for the Lua socket connection pool table */ - lua_pushlightuserdata(L, &ngx_http_lua_socket_pool_key); + lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( + socket_pool_key)); lua_createtable(L, 0, 8 /* nrec */); lua_rawset(L, LUA_REGISTRYINDEX); #if (NGX_PCRE) /* create the registry entry for the Lua precompiled regex object cache */ - lua_pushlightuserdata(L, &ngx_http_lua_regex_cache_key); + lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( + regex_cache_key)); lua_createtable(L, 0, 16 /* nrec */); lua_rawset(L, LUA_REGISTRYINDEX); #endif /* {{{ register table to cache user code: * { [(string)cache_key] = } */ - lua_pushlightuserdata(L, &ngx_http_lua_code_cache_key); + lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( + code_cache_key)); lua_createtable(L, 0, 8 /* nrec */); lua_rawset(L, LUA_REGISTRYINDEX); /* }}} */ @@ -695,9 +705,6 @@ ngx_http_lua_init_globals(lua_State *L, ngx_cycle_t *cycle, ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "lua initializing lua globals"); - lua_pushlightuserdata(L, cycle); - lua_setglobal(L, "__ngx_cycle"); - #if defined(NDK) && NDK ngx_http_lua_inject_ndk_api(L); #endif /* defined(NDK) && NDK */ @@ -756,6 +763,50 @@ ngx_http_lua_inject_ngx_api(lua_State *L, ngx_http_lua_main_conf_t *lmcf, lua_setglobal(L, "ngx"); ngx_http_lua_inject_coroutine_api(log, L); + +#ifdef OPENRESTY_LUAJIT + { + int rc; + + const char buf[] = + "local ngx_log = ngx.log\n" + "local ngx_WARN = ngx.WARN\n" + "local type = type\n" + "local ngx_get_phase = ngx.get_phase\n" + "local traceback = require 'debug'.traceback\n" + "local function newindex(table, key, value)\n" + "rawset(table, key, value)\n" + "local phase = ngx_get_phase()\n" + "if phase == 'init_worker' or phase == 'init' then\n" + "return\n" + "end\n" + "ngx_log(ngx_WARN, 'lua http attempting to write to the lua " + "global variable \\'', tostring(key), " + "'\\'\\n', traceback())\n" + "end\n" + "setmetatable(_G, { __newindex = newindex })\n" + ; + + rc = luaL_loadbuffer(L, buf, sizeof(buf) - 1, "=_G write guard"); + + if (rc != 0) { + ngx_log_error(NGX_LOG_ERR, log, 0, + "failed to load Lua code for the _G write guard: ", + "%i: %s", rc, lua_tostring(L, -1)); + + lua_pop(L, 1); + return; + } + + rc = lua_pcall(L, 0, 0, 0); + if (rc != 0) { + ngx_log_error(NGX_LOG_ERR, log, 0, + "failed to run Lua code for the _G write guard: %s", + rc, lua_tostring(L, -1)); + lua_pop(L, 1); + } + } +#endif } @@ -2954,12 +3005,12 @@ ngx_http_lua_param_get(lua_State *L) | NGX_HTTP_LUA_CONTEXT_BODY_FILTER); if (ctx->context & (NGX_HTTP_LUA_CONTEXT_SET)) { - return ngx_http_lua_setby_param_get(L); + return ngx_http_lua_setby_param_get(L, r); } /* ctx->context & (NGX_HTTP_LUA_CONTEXT_BODY_FILTER) */ - return ngx_http_lua_body_filter_param_get(L); + return ngx_http_lua_body_filter_param_get(L, r); } @@ -3156,7 +3207,8 @@ ngx_http_lua_finalize_threads(ngx_http_request_t *r, ngx_http_lua_probe_thread_delete(r, coctx->co, ctx); - lua_pushlightuserdata(L, &ngx_http_lua_coroutines_key); + lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( + coroutines_key)); lua_rawget(L, LUA_REGISTRYINDEX); inited = 1; @@ -3194,7 +3246,8 @@ ngx_http_lua_finalize_threads(ngx_http_request_t *r, ngx_http_lua_probe_thread_delete(r, coctx->co, ctx); if (!inited) { - lua_pushlightuserdata(L, &ngx_http_lua_coroutines_key); + lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( + coroutines_key)); lua_rawget(L, LUA_REGISTRYINDEX); inited = 1; } @@ -3223,7 +3276,8 @@ ngx_http_lua_finalize_threads(ngx_http_request_t *r, ngx_http_lua_probe_thread_delete(r, coctx->co, ctx); if (!inited) { - lua_pushlightuserdata(L, &ngx_http_lua_coroutines_key); + lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask( + coroutines_key)); lua_rawget(L, LUA_REGISTRYINDEX); inited = 1; } @@ -3778,6 +3832,11 @@ ngx_http_lua_init_vm(lua_State *parent_vm, ngx_cycle_t *cycle, *pcln = cln; } +#ifdef OPENRESTY_LUAJIT + /* load FFI library first since cdata needs it */ + luaopen_ffi(L); +#endif + if (lmcf->preload_hooks) { /* register the 3rd-party module's preload hooks */ @@ -4041,7 +4100,12 @@ ngx_http_lua_get_raw_phase_context(lua_State *L) ngx_http_request_t *r; ngx_http_lua_ctx_t *ctx; +#ifdef OPENRESTY_LUAJIT + r = lua_getexdata(L); +#else r = lua_touserdata(L, 1); +#endif + if (r == NULL) { return 0; } diff --git a/src/ngx_http_lua_util.h b/src/ngx_http_lua_util.h index 7dcc6f7585..052aa1737e 100644 --- a/src/ngx_http_lua_util.h +++ b/src/ngx_http_lua_util.h @@ -188,7 +188,9 @@ ngx_int_t ngx_http_lua_open_and_stat_file(u_char *name, ngx_chain_t *ngx_http_lua_chain_get_free_buf(ngx_log_t *log, ngx_pool_t *p, ngx_chain_t **free, size_t len); +#ifndef OPENRESTY_LUAJIT void ngx_http_lua_create_new_globals_table(lua_State *L, int narr, int nrec); +#endif int ngx_http_lua_traceback(lua_State *L); @@ -334,6 +336,9 @@ ngx_http_lua_get_lua_vm(ngx_http_request_t *r, ngx_http_lua_ctx_t *ctx) static ngx_inline ngx_http_request_t * ngx_http_lua_get_req(lua_State *L) { +#ifdef OPENRESTY_LUAJIT + return lua_getexdata(L); +#else ngx_http_request_t *r; lua_getglobal(L, ngx_http_lua_req_key); @@ -341,14 +346,19 @@ ngx_http_lua_get_req(lua_State *L) lua_pop(L, 1); return r; +#endif } static ngx_inline void ngx_http_lua_set_req(lua_State *L, ngx_http_request_t *r) { +#ifdef OPENRESTY_LUAJIT + lua_setexdata(L, (void *) r); +#else lua_pushlightuserdata(L, r); lua_setglobal(L, ngx_http_lua_req_key); +#endif } diff --git a/t/001-set.t b/t/001-set.t index ba8f22cb68..60ab2ff471 100644 --- a/t/001-set.t +++ b/t/001-set.t @@ -4,7 +4,7 @@ use Test::Nginx::Socket::Lua; repeat_each(2); -plan tests => repeat_each() * (blocks() * 3 + 4); +plan tests => repeat_each() * (blocks() * 3 + 5); #log_level("warn"); no_long_string(); @@ -592,25 +592,30 @@ failed to run set_by_lua*: unknown reason -=== TEST 37: globals get cleared for every single request +=== TEST 37: globals are shared in all requests. --- config location /lua { - set_by_lua $res ' + set_by_lua_block $res { if not foo then foo = 1 else + ngx.log(ngx.INFO, "old foo: ", foo) foo = foo + 1 end return foo - '; + } echo $res; } --- request GET /lua ---- response_body -1 +--- response_body_like chomp +\A[12] +\z --- no_error_log [error] +--- grep_error_log eval: qr/(old foo: \d+|write to the lua global variable '\w+')/ +--- grep_error_log_out eval +["write to the lua global variable 'foo'\n", "old foo: 1\n"] diff --git a/t/014-bugs.t b/t/014-bugs.t index 9aadff0e25..545978ccb6 100644 --- a/t/014-bugs.t +++ b/t/014-bugs.t @@ -579,7 +579,7 @@ $s -=== TEST 26: unexpected globals sharing by using _G +=== TEST 26: globals sharing by using _G --- config location /test { content_by_lua ' @@ -593,12 +593,12 @@ $s } --- pipelined_requests eval ["GET /test", "GET /test", "GET /test"] ---- response_body eval -["0", "0", "0"] +--- response_body_like eval +[qr/\A[036]\z/, qr/\A[147]\z/, qr/\A[258]\z/] -=== TEST 27: unexpected globals sharing by using _G (set_by_lua*) +=== TEST 27: globals sharing by using _G (set_by_lua*) --- config location /test { set_by_lua $a ' @@ -613,12 +613,12 @@ $s } --- pipelined_requests eval ["GET /test", "GET /test", "GET /test"] ---- response_body eval -["0", "0", "0"] +--- response_body_like eval +[qr/\A[036]\z/, qr/\A[147]\z/, qr/\A[258]\z/] -=== TEST 28: unexpected globals sharing by using _G (log_by_lua*) +=== TEST 28: globals sharing by using _G (log_by_lua*) --- http_config lua_shared_dict log_dict 100k; --- config @@ -633,19 +633,19 @@ $s if _G.t then _G.t = _G.t + 1 else - _G.t = 0 + _G.t = 1 end log_dict:set("cnt", t) '; } --- pipelined_requests eval ["GET /test", "GET /test", "GET /test"] ---- response_body eval -["0", "0", "0"] +--- response_body_like eval +[qr/\A[036]\z/, qr/\A[147]\z/, qr/\A[258]\z/] -=== TEST 29: unexpected globals sharing by using _G (header_filter_by_lua*) +=== TEST 29: globals sharing by using _G (header_filter_by_lua*) --- config location /test { header_filter_by_lua ' @@ -663,12 +663,12 @@ $s } --- pipelined_requests eval ["GET /test", "GET /test", "GET /test"] ---- response_body eval -["0", "0", "0"] +--- response_body_like eval +[qr/\A[036]\z/, qr/\A[147]\z/, qr/\A[258]\z/] -=== TEST 30: unexpected globals sharing by using _G (body_filter_by_lua*) +=== TEST 30: globals sharing by using _G (body_filter_by_lua*) --- config location /test { body_filter_by_lua ' @@ -686,8 +686,9 @@ $s } --- request GET /test ---- response_body -a0 +--- response_body_like eval +qr/\Aa[036] +\z/ --- no_error_log [error] diff --git a/t/041-header-filter.t b/t/041-header-filter.t index 7d8ee74673..5e66e184d7 100644 --- a/t/041-header-filter.t +++ b/t/041-header-filter.t @@ -10,7 +10,7 @@ log_level('debug'); repeat_each(2); -plan tests => repeat_each() * 94; +plan tests => repeat_each() * (blocks() * 2 + 13); #no_diff(); #no_long_string(); @@ -416,7 +416,7 @@ lua release ngx.ctx -=== TEST 20: global got cleared for each single request +=== TEST 20: globals are shared by all requests --- config location /lua { set $foo ''; @@ -428,6 +428,7 @@ lua release ngx.ctx if not foo then foo = 1 else + ngx.log(ngx.INFO, "old foo: ", foo) foo = foo + 1 end ngx.var.foo = foo @@ -435,10 +436,13 @@ lua release ngx.ctx } --- request GET /lua ---- response_body -1 +--- response_body_like +^[12]$ --- no_error_log [error] +--- grep_error_log eval: qr/old foo: \d+/ +--- grep_error_log_out eval +["", "old foo: 1\n"] diff --git a/t/073-backtrace.t b/t/073-backtrace.t index 6c5469218d..94dc984d43 100644 --- a/t/073-backtrace.t +++ b/t/073-backtrace.t @@ -37,7 +37,7 @@ GET /lua attempt to call global 'lua_concat' : in function 'bar' :5: in function 'foo' -:7: in function +:7: in main chunk @@ -64,7 +64,7 @@ GET /lua " in function 'error'", ": in function 'bar'", ":5: in function 'foo'", -qr/:7: in function /, +qr/:7: in main chunk/, ] @@ -125,7 +125,7 @@ probe process("$LIBLUA_PATH").function("lua_concat") { :63: in function 'func16' :67: in function 'func17' :71: in function 'func18' -:74: in function +:74: in main chunk diff --git a/t/075-logby.t b/t/075-logby.t index 520c62e314..84c7c466ef 100644 --- a/t/075-logby.t +++ b/t/075-logby.t @@ -220,7 +220,7 @@ failed to run log_by_lua*: unknown reason -=== TEST 11: globals get cleared for every single request +=== TEST 11: globals sharing --- config location /lua { echo ok; @@ -228,6 +228,7 @@ failed to run log_by_lua*: unknown reason if not foo then foo = 1 else + ngx.log(ngx.INFO, "old foo: ", foo) foo = foo + 1 end ngx.log(ngx.WARN, "foo = ", foo) @@ -237,8 +238,9 @@ failed to run log_by_lua*: unknown reason GET /lua --- response_body ok ---- error_log -foo = 1 +--- grep_error_log eval: qr/old foo: \d+/ +--- grep_error_log_out eval +["", "old foo: 1\n"] diff --git a/t/081-bytecode.t b/t/081-bytecode.t index cb50e945d3..29b2f758ab 100644 --- a/t/081-bytecode.t +++ b/t/081-bytecode.t @@ -85,7 +85,7 @@ __DATA__ --- response_body error --- error_log eval -qr/failed to load external Lua file ".*?test\.lua": bad byte-code header/ +qr/failed to load external Lua file ".*?test\.lua": .* cannot load incompatible bytecode/ @@ -121,7 +121,7 @@ qr/failed to load external Lua file ".*?test\.lua": bad byte-code header/ --- response_body error --- error_log -bytecode format version unsupported +cannot load incompatible bytecode @@ -320,7 +320,7 @@ ngx.status = 201 ngx.say("hello from Lua!") --- config location = /t { content_by_lua_block { - local f = assert(loadstring("a = a and a + 1 or 1 ngx.say('a = ', a)", "=code")) + local f = assert(loadstring("local a = 1 ngx.say('a = ', a)", "=code")) local bc = string.dump(f) local f = assert(io.open("t/servroot/html/a.luac", "w")) f:write(bc) @@ -349,7 +349,7 @@ a = 1 --- config location = /t { content_by_lua_block { - local f = assert(loadstring("a = a and a + 1 or 1 ngx.say('a = ', a)", "=code")) + local f = assert(loadstring("local a = 1 ngx.say('a = ', a)", "=code")) local bc = string.dump(f, true) local f = assert(io.open("t/servroot/html/a.luac", "w")) f:write(bc) diff --git a/t/094-uthread-exit.t b/t/094-uthread-exit.t index 2f7d9ba731..0b31a800b8 100644 --- a/t/094-uthread-exit.t +++ b/t/094-uthread-exit.t @@ -1059,7 +1059,7 @@ after location /lua { client_body_timeout 12000ms; content_by_lua ' - function f() + local function f() ngx.say("hello in thread") ngx.sleep(0.1) ngx.exit(0) @@ -1315,7 +1315,7 @@ attempt to abort with pending subrequests location /lua { client_body_timeout 12000ms; content_by_lua ' - function f() + local function f() ngx.location.capture_multi{ {"/echo"}, {"/sleep"} @@ -1407,7 +1407,7 @@ attempt to abort with pending subrequests location /lua { client_body_timeout 12000ms; content_by_lua ' - function f() + local function f() ngx.say("hello in thread") ngx.sleep(0.1) ngx.exit(444) @@ -1490,7 +1490,7 @@ free request location /lua { client_body_timeout 12000ms; content_by_lua ' - function f() + local function f() ngx.say("hello in thread") ngx.sleep(0.1) ngx.exit(408) @@ -1573,7 +1573,7 @@ free request location /lua { client_body_timeout 12000ms; content_by_lua ' - function f() + local function f() ngx.say("hello in thread") ngx.sleep(0.1) ngx.exit(499) diff --git a/t/095-uthread-exec.t b/t/095-uthread-exec.t index 56156c48a8..ad0c1888a0 100644 --- a/t/095-uthread-exec.t +++ b/t/095-uthread-exec.t @@ -348,7 +348,7 @@ attempt to abort with pending subrequests location /lua { client_body_timeout 12000ms; content_by_lua ' - function f() + local function f() ngx.location.capture("/sleep") ngx.say("end") end diff --git a/t/096-uthread-redirect.t b/t/096-uthread-redirect.t index 003c6423de..73b2bf1eec 100644 --- a/t/096-uthread-redirect.t +++ b/t/096-uthread-redirect.t @@ -194,7 +194,7 @@ free request location /lua { client_body_timeout 12000ms; content_by_lua ' - function f() + local function f() ngx.location.capture_multi{ {"/echo"}, {"/sleep"} diff --git a/t/106-timer.t b/t/106-timer.t index 3e4741e50c..fa25e18795 100644 --- a/t/106-timer.t +++ b/t/106-timer.t @@ -76,7 +76,7 @@ qr/\[lua\] content_by_lua\(nginx\.conf:\d+\):\d+: elapsed: 0\.0(?:4[4-9]|5[0-6]) -=== TEST 2: separated global env +=== TEST 2: globals are shared --- config location /t { content_by_lua ' @@ -104,7 +104,7 @@ F(ngx_http_lua_timer_handler) { --- response_body registered timer -foo = nil +foo = 3 --- wait: 0.1 --- no_error_log diff --git a/t/130-internal-api.t b/t/130-internal-api.t index eba0980f8f..2158e878be 100644 --- a/t/130-internal-api.t +++ b/t/130-internal-api.t @@ -8,7 +8,7 @@ use Test::Nginx::Socket::Lua; repeat_each(2); -plan tests => repeat_each() * 3; +plan tests => repeat_each() * blocks() * 3; #no_diff(); no_long_string(); @@ -19,12 +19,7 @@ run_tests(); __DATA__ -=== TEST 1: __ngx_req and __ngx_cycle ---- http_config - init_by_lua ' - my_cycle = __ngx_cycle - '; - +=== TEST 1: req --- config location = /t { content_by_lua ' @@ -32,18 +27,14 @@ __DATA__ local function tonum(ud) return tonumber(ffi.cast("uintptr_t", ud)) end - ngx.say(string.format("init: cycle=%#x", tonum(my_cycle))) - ngx.say(string.format("content cycle=%#x", tonum(__ngx_cycle))) - ngx.say(string.format("content req=%#x", tonum(__ngx_req))) + ngx.say(string.format("content req=%#x", tonum(exdata()))) '; } --- request GET /t --- response_body_like chop -^init: cycle=(0x[a-f0-9]{4,}) -content cycle=\1 -content req=0x[a-f0-9]{4,} +^content req=0x[a-f0-9]{4,} $ --- no_error_log [error] diff --git a/t/140-ssl-c-api.t b/t/140-ssl-c-api.t index 8734d1477d..a77f5d4c05 100644 --- a/t/140-ssl-c-api.t +++ b/t/140-ssl-c-api.t @@ -10,6 +10,7 @@ my $openssl_version = eval { `$NginxBinary -V 2>&1` }; if ($openssl_version =~ m/built with OpenSSL (0|1\.0\.(?:0|1[^\d]|2[a-d]).*)/) { plan(skip_all => "too old OpenSSL, need 1.0.2e, was $1"); + } else { plan tests => repeat_each() * (blocks() * 5 + 1); } @@ -68,7 +69,7 @@ _EOC_ my $http_config = $block->http_config || ''; $http_config .= <<'_EOC_'; -lua_package_path "$prefix/html/?.lua;;"; +lua_package_path "$prefix/html/?.lua;../lua-resty-core/lib/?.lua;;"; _EOC_ $block->set_value("http_config", $http_config); }); @@ -91,8 +92,8 @@ __DATA__ local errmsg = ffi.new("char *[1]") - local r = getfenv(0).__ngx_req - if not r then + local r = require "resty.core.base" .get_request() + if r == nil then ngx.log(ngx.ERR, "no request found") return end @@ -245,8 +246,8 @@ lua ssl server name: "test.com" local errmsg = ffi.new("char *[1]") - local r = getfenv(0).__ngx_req - if not r then + local r = require "resty.core.base" .get_request() + if r == nil then ngx.log(ngx.ERR, "no request found") return end @@ -399,8 +400,8 @@ lua ssl server name: "test.com" local errmsg = ffi.new("char *[1]") - local r = getfenv(0).__ngx_req - if not r then + local r = require "resty.core.base" .get_request() + if r == nil then ngx.log(ngx.ERR, "no request found") return end @@ -528,8 +529,8 @@ failed to parse PEM priv key: PEM_read_bio_PrivateKey() failed local errmsg = ffi.new("char *[1]") - local r = getfenv(0).__ngx_req - if not r then + local r = require "resty.core.base" .get_request() + if r == nil then ngx.log(ngx.ERR, "no request found") return end @@ -678,8 +679,8 @@ lua ssl server name: "test.com" local errmsg = ffi.new("char *[1]") - local r = getfenv(0).__ngx_req - if not r then + local r = require "resty.core.base" .get_request() + if r == nil then ngx.log(ngx.ERR, "no request found") return end diff --git a/t/143-ssl-session-fetch.t b/t/143-ssl-session-fetch.t index 4dc992d370..da45aa34c6 100644 --- a/t/143-ssl-session-fetch.t +++ b/t/143-ssl-session-fetch.t @@ -1114,3 +1114,108 @@ qr/ssl_session_fetch_by_lua_block:1: ssl fetch sess by lua is running!/s [error] [alert] [emerg] + + + +=== TEST 14: keep global variable in ssl_session_(store|fetch)_by_lua when OpenResty LuaJIT is used +--- http_config + ssl_session_store_by_lua_block { + ngx.log(ngx.WARN, "new foo: ", foo) + if not foo then + foo = 1 + else + ngx.log(ngx.WARN, "old foo: ", foo) + foo = foo + 1 + end + } + ssl_session_fetch_by_lua_block { + ngx.log(ngx.WARN, "new bar: ", foo) + if not bar then + bar = 1 + else + ngx.log(ngx.WARN, "old bar: ", bar) + bar = bar + 1 + end + } + + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + ssl_certificate ../../cert/test.crt; + ssl_certificate_key ../../cert/test.key; + ssl_session_tickets off; + + server_tokens off; + location /foo { + content_by_lua_block { + ngx.say("foo: ", foo) + ngx.say("bar: ", bar) + } + } + } +--- config + server_tokens off; + lua_ssl_trusted_certificate ../../cert/test.crt; + + location /t { + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(2000) + + local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") + if not ok then + ngx.say("failed to connect: ", err) + return + end + + local sess, err = sock:sslhandshake(package.loaded.session, "test.com", true) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + package.loaded.session = sess + + local req = "GET /foo HTTP/1.0\r\nHost: test.com\r\nConnection: close\r\n\r\n" + local bytes, err = sock:send(req) + if not bytes then + ngx.say("failed to send http request: ", err) + return + end + + while true do + local line, err = sock:receive() + if not line then + -- ngx.say("failed to receive response status line: ", err) + break + end + + local m, err = ngx.re.match(line, "^foo: (.*)$", "jo") + if err then + ngx.say("failed to match line: ", err) + end + + if m and m[1] then + ngx.print(m[1]) + end + end + + local ok, err = sock:close() + ngx.say("done") + end -- do + } + } + +--- request +GET /t +--- response_body_like eval +qr/^(1|2|3)done$/ +--- grep_error_log eval: qr/old (foo|bar): \d+/ +--- grep_error_log_out eval +["", "old foo: 1\n", "old bar: 1\nold foo: 2\n"] +--- no_error_log +[error] +[alert] +[emerg] diff --git a/t/152-timer-every.t b/t/152-timer-every.t index c8d62e704d..7b42d2d724 100644 --- a/t/152-timer-every.t +++ b/t/152-timer-every.t @@ -63,7 +63,7 @@ qr/\[lua\] content_by_lua\(nginx\.conf:\d+\):\d+: elapsed: 0\.(?:09|10)\d*, cont -=== TEST 2: separated global env +=== TEST 2: shared global env --- config location /t { content_by_lua_block { @@ -84,7 +84,7 @@ qr/\[lua\] content_by_lua\(nginx\.conf:\d+\):\d+: elapsed: 0\.(?:09|10)\d*, cont --- request GET /t --- response_body -foo = nil +foo = 3 --- wait: 0.12 --- no_error_log [error] diff --git a/t/157-global-var.t b/t/157-global-var.t new file mode 100644 index 0000000000..69fed4fd17 --- /dev/null +++ b/t/157-global-var.t @@ -0,0 +1,489 @@ +# vim:set ft= ts=4 sw=4 et fdm=marker: + +use Test::Nginx::Socket::Lua; + +log_level('debug'); + +repeat_each(2); + +plan tests => repeat_each() * (blocks() * 3 + 14); + +our $HtmlDir = html_dir; + +$ENV{TEST_NGINX_HTML_DIR} ||= html_dir(); + +no_long_string(); + +sub read_file { + my $infile = shift; + open my $in, $infile + or die "cannot open $infile for reading: $!"; + my $cert = do { local $/; <$in> }; + close $in; + $cert; +} + +our $TestCertificate = read_file("t/cert/test.crt"); +our $TestCertificateKey = read_file("t/cert/test.key"); + +add_block_preprocessor(sub { + my $block = shift; + + if (!defined $block->error_log) { + $block->set_value("no_error_log", "[error]"); + } + + if (!defined $block->request) { + $block->set_value("request", "GET /t"); + } + +}); + +run_tests(); + +__DATA__ + +=== TEST 1: set_by_lua +--- config + location /t { + set_by_lua_block $res { + if not foo then + foo = 1 + else + ngx.log(ngx.WARN, "old foo: ", foo) + foo = foo + 1 + end + return foo + } + echo $res; + } +--- response_body_like eval +qr/[12]/ +--- grep_error_log eval: qr/(old foo: \d+|write to the lua global variable '\w+')/ +--- grep_error_log_out eval +["write to the lua global variable 'foo'\n", "old foo: 1\n"] + + + +=== TEST 2: rewrite_by_lua +--- config + location /t { + rewrite_by_lua_block { + if not foo then + foo = 1 + else + ngx.log(ngx.WARN, "old foo: ", foo) + foo = foo + 1 + end + ngx.say(foo) + } + } +--- response_body_like eval +qr/[12]/ +--- grep_error_log eval: qr/(old foo: \d+|write to the lua global variable '\w+')/ +--- grep_error_log_out eval +["write to the lua global variable 'foo'\n", "old foo: 1\n"] + + + +=== TEST 3: access_by_lua +--- config + location /t { + access_by_lua_block { + if not foo then + foo = 1 + else + ngx.log(ngx.WARN, "old foo: ", foo) + foo = foo + 1 + end + ngx.say(foo) + } + } +--- response_body_like eval +qr/[12]/ +--- grep_error_log eval: qr/(old foo: \d+|write to the lua global variable '\w+')/ +--- grep_error_log_out eval +["write to the lua global variable 'foo'\n", "old foo: 1\n"] + + + +=== TEST 4: content_by_lua +--- config + location /t { + content_by_lua_block { + if not foo then + foo = 1 + else + ngx.log(ngx.WARN, "old foo: ", foo) + foo = foo + 1 + end + ngx.say(foo) + } + } +--- response_body_like eval +qr/[12]/ +--- grep_error_log eval: qr/(old foo: \d+|write to the lua global variable '\w+')/ +--- grep_error_log_out eval +["write to the lua global variable 'foo'\n", "old foo: 1\n"] + + + +=== TEST 5: header_filter_by_lua +--- config + location /t { + content_by_lua_block { + ngx.say(foo) + } + header_filter_by_lua_block { + if not foo then + foo = 1 + else + ngx.log(ngx.WARN, "old foo: ", foo) + foo = foo + 1 + end + } + } +--- response_body_like eval +qr/^(nil|1)$/ +--- grep_error_log eval: qr/(old foo: \d+|write to the lua global variable '\w+')/ +--- grep_error_log_out eval +["write to the lua global variable 'foo'\n", "old foo: 1\n"] + + + +=== TEST 6: body_filter_by_lua +--- config + location /t { + content_by_lua_block { + ngx.say(foo) + } + body_filter_by_lua_block { + if not foo then + foo = 1 + else + ngx.log(ngx.WARN, "old foo: ", foo) + foo = foo + 1 + end + } + } +--- response_body_like eval +qr/^(nil|2)$/ +--- grep_error_log eval: qr/(old foo: \d+|write to the lua global variable '\w+')/ +--- grep_error_log_out eval +["write to the lua global variable 'foo' +old foo: 1\n", "old foo: 2\nold foo: 3\n"] + + + +=== TEST 7: log_by_lua +--- config + location /t { + content_by_lua_block { + ngx.say(foo) + } + log_by_lua_block { + if not foo then + foo = 1 + else + ngx.log(ngx.WARN, "old foo: ", foo) + foo = foo + 1 + end + } + } +--- response_body_like eval +qr/^(nil|1)$/ +--- grep_error_log eval: qr/(old foo: \d+|write to the lua global variable '\w+')/ +--- grep_error_log_out eval +["write to the lua global variable 'foo'\n", "old foo: 1\n"] + + + +=== TEST 8: ssl_certificate_by_lua +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + ssl_certificate_by_lua_block { + if not foo then + foo = 1 + else + ngx.log(ngx.WARN, "old foo: ", foo) + foo = foo + 1 + end + } + ssl_certificate ../../cert/test.crt; + ssl_certificate_key ../../cert/test.key; + + server_tokens off; + location /foo { + content_by_lua_block { + ngx.say("foo: ", foo) + } + } + } +--- config + server_tokens off; + lua_ssl_trusted_certificate ../../cert/test.crt; + + location /t { + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(2000) + + local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") + if not ok then + ngx.say("failed to connect: ", err) + return + end + + -- ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(nil, "test.com", true) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + -- ngx.say("ssl handshake: ", type(sess)) + + local req = "GET /foo HTTP/1.0\r\nHost: test.com\r\nConnection: close\r\n\r\n" + local bytes, err = sock:send(req) + if not bytes then + ngx.say("failed to send http request: ", err) + return + end + + -- ngx.say("sent http request: ", bytes, " bytes.") + + while true do + local line, err = sock:receive() + if not line then + -- ngx.say("failed to receive response status line: ", err) + break + end + + local m, err = ngx.re.match(line, "^foo: (.*)$", "jo") + if err then + ngx.say("failed to match line: ", err) + end + + if m and m[1] then + ngx.print(m[1]) + end + end + + local ok, err = sock:close() + ngx.say("done") + end -- do + } + } + +--- response_body_like eval +qr/^(1|2)done$/ +--- grep_error_log eval: qr/(old foo: \d+|write to the lua global variable '\w+')/ +--- grep_error_log_out eval +["write to the lua global variable 'foo'\n", "old foo: 1\n"] + + + +=== TEST 9: timer +--- config + location /t { + content_by_lua_block { + local function f() + if not foo then + foo = 1 + else + ngx.log(ngx.WARN, "old foo: ", foo) + foo = foo + 1 + end + end + local ok, err = ngx.timer.at(0, f) + if not ok then + ngx.say("failed to set timer: ", err) + return + end + ngx.sleep(0.01) + ngx.say(foo) + } + } +--- response_body_like eval +qr/^(1|2)$/ +--- grep_error_log eval: qr/(old foo: \d+|write to the lua global variable '\w+')/ +--- grep_error_log_out eval +["write to the lua global variable 'foo'\n", "old foo: 1\n"] + + + +=== TEST 10: init_by_lua +--- http_config + init_by_lua_block { + foo = 1 + } +--- config + location /t { + content_by_lua_block { + if not foo then + foo = 1 + else + ngx.log(ngx.WARN, "old foo: ", foo) + foo = foo + 1 + end + ngx.say(foo) + } + } +--- response_body_like eval +qr/^(2|3)$/ +--- grep_error_log eval: qr/old foo: \d+/ +--- grep_error_log_out eval +["old foo: 1\n", "old foo: 2\n"] + + + +=== TEST 11: init_worker_by_lua +--- http_config + init_worker_by_lua_block { + if not foo then + foo = 1 + else + ngx.log(ngx.WARN, "old foo: ", foo) + foo = foo + 1 + end + } +--- config + location /t { + content_by_lua_block { + if not foo then + foo = 1 + else + ngx.log(ngx.WARN, "old foo: ", foo) + foo = foo + 1 + end + ngx.say(foo) + } + } +--- response_body_like eval +qr/^(2|3)$/ +--- grep_error_log eval: qr/old foo: \d+/ +--- grep_error_log_out eval +["old foo: 1\n", "old foo: 2\n"] + + + +=== TEST 12: init_by_lua + init_worker_by_lua +--- http_config + init_by_lua_block { + if not foo then + foo = 1 + else + ngx.log(ngx.WARN, "old foo: ", foo) + foo = foo + 1 + end + } + init_worker_by_lua_block { + if not foo then + foo = 1 + else + ngx.log(ngx.WARN, "old foo: ", foo) + foo = foo + 1 + end + } +--- config + location /t { + content_by_lua_block { + if not foo then + foo = 1 + else + ngx.log(ngx.WARN, "old foo: ", foo) + foo = foo + 1 + end + ngx.say(foo) + } + } +--- response_body_like eval +qr/^(3|4)$/ +--- grep_error_log eval: qr/old foo: \d+/ +--- grep_error_log_out eval +["old foo: 1\nold foo: 2\n", "old foo: 3\n"] + + + +=== TEST 13: don't show warn messages in init/init_worker +--- http_config + init_by_lua_block { + foo = 1 + } + + init_worker_by_lua_block { + bar = 2 + } +--- config + location /t { + content_by_lua_block { + ngx.say(foo) + ngx.say(bar) + } + } +--- response_body +1 +2 +--- no_error_log +setting global variable + + + +=== TEST 14: uthread +--- config + location /t { + content_by_lua_block { + local function f() + if not foo then + foo = 1 + else + ngx.log(ngx.WARN, "old foo: ", foo) + foo = foo + 1 + end + end + local ok, err = ngx.thread.spawn(f) + if not ok then + ngx.say("failed to set timer: ", err) + return + end + ngx.sleep(0.01) + ngx.say(foo) + } + } +--- response_body_like eval +qr/^(1|2)$/ +--- grep_error_log eval: qr/(old foo: \d+|write to the lua global variable '\w+')/ +--- grep_error_log_out eval +["write to the lua global variable 'foo'\n", "old foo: 1\n"] + + + +=== TEST 15: balancer_by_lua +--- http_config + upstream backend { + server 0.0.0.1; + balancer_by_lua_block { + if not foo then + foo = 1 + else + ngx.log(ngx.WARN, "old foo: ", foo) + foo = foo + 1 + end + } + } +--- config + location = /t { + proxy_pass http://backend; + } +--- response_body_like: 502 Bad Gateway +--- error_code: 502 +--- error_log +connect() to 0.0.0.1:80 failed +--- grep_error_log eval: qr/(old foo: \d+|write to the lua global variable '\w+')/ +--- grep_error_log_out eval +["write to the lua global variable 'foo'\n", "old foo: 1\n"] diff --git a/t/data/fake-shm-module/ngx_http_lua_fake_shm_module.c b/t/data/fake-shm-module/ngx_http_lua_fake_shm_module.c index 0286853e54..ffc32f5795 100644 --- a/t/data/fake-shm-module/ngx_http_lua_fake_shm_module.c +++ b/t/data/fake-shm-module/ngx_http_lua_fake_shm_module.c @@ -213,10 +213,9 @@ ngx_http_lua_fake_shm_preload(lua_State *L) ngx_uint_t i; ngx_shm_zone_t **zone; + ngx_shm_zone_t **zone_udata; - lua_getglobal(L, "__ngx_cycle"); - cycle = lua_touserdata(L, -1); - lua_pop(L, 1); + cycle = (ngx_cycle_t *) ngx_cycle; hmcf_ctx = (ngx_http_conf_ctx_t *) cycle->conf_ctx[ngx_http_module.index]; lfsmcf = hmcf_ctx->main_conf[ngx_http_lua_fake_shm_module.ctx_index]; @@ -242,7 +241,9 @@ ngx_http_lua_fake_shm_preload(lua_State *L) lua_createtable(L, 1 /* narr */, 0 /* nrec */); /* table of zone[i] */ - lua_pushlightuserdata(L, zone[i]); /* shared mt key ud */ + zone_udata = lua_newuserdata(L, sizeof(ngx_shm_zone_t *)); + /* shared mt key ud */ + *zone_udata = zone[i]; lua_rawseti(L, -2, 1); /* {zone[i]} */ lua_pushvalue(L, -3); /* shared mt key ud mt */ lua_setmetatable(L, -2); /* shared mt key ud */ @@ -262,9 +263,10 @@ ngx_http_lua_fake_shm_preload(lua_State *L) static int ngx_http_lua_fake_shm_get_info(lua_State *L) { - ngx_int_t n; - ngx_shm_zone_t *zone; - ngx_http_lua_fake_shm_ctx_t *ctx; + ngx_int_t n; + ngx_shm_zone_t *zone; + ngx_shm_zone_t **zone_udata; + ngx_http_lua_fake_shm_ctx_t *ctx; n = lua_gettop(L); @@ -276,13 +278,15 @@ ngx_http_lua_fake_shm_get_info(lua_State *L) luaL_checktype(L, 1, LUA_TTABLE); lua_rawgeti(L, 1, 1); - zone = lua_touserdata(L, -1); + zone_udata = lua_touserdata(L, -1); lua_pop(L, 1); - if (zone == NULL) { + if (zone_udata == NULL) { return luaL_error(L, "bad \"zone\" argument"); } + zone = *zone_udata; + ctx = (ngx_http_lua_fake_shm_ctx_t *) zone->data; lua_pushlstring(L, (char *) zone->shm.name.data, zone->shm.name.len); diff --git a/util/build.sh b/util/build.sh index 164bf9f9a2..14e9fd46d9 100755 --- a/util/build.sh +++ b/util/build.sh @@ -22,6 +22,8 @@ force=$2 #--without-http_referer_module \ #--with-http_spdy_module \ +add_fake_shm_module="--add-module=$root/t/data/fake-shm-module" + time ngx-build $force $version \ --with-pcre-jit \ --with-ipv6 \ @@ -55,7 +57,7 @@ time ngx-build $force $version \ --add-module=$root/../redis2-nginx-module \ --add-module=$root/../stream-lua-nginx-module \ --add-module=$root/t/data/fake-module \ - --add-module=$root/t/data/fake-shm-module \ + $add_fake_shm_module \ --add-module=$root/t/data/fake-delayed-load-module \ --with-http_gunzip_module \ --with-http_dav_module \