diff --git a/src/ngx_http_lua_common.h b/src/ngx_http_lua_common.h index 017e2a0434..8e7230e294 100644 --- a/src/ngx_http_lua_common.h +++ b/src/ngx_http_lua_common.h @@ -141,6 +141,7 @@ typedef struct { #define NGX_HTTP_LUA_CONTEXT_SSL_SESS_FETCH 0x1000 #define NGX_HTTP_LUA_CONTEXT_EXIT_WORKER 0x2000 #define NGX_HTTP_LUA_CONTEXT_SSL_CLIENT_HELLO 0x4000 +#define NGX_HTTP_LUA_CONTEXT_INIT 0x8000 #define NGX_HTTP_LUA_FFI_NO_REQ_CTX -100 diff --git a/src/ngx_http_lua_initworkerby.c b/src/ngx_http_lua_initworkerby.c index 7013deb73c..3235a4d30a 100644 --- a/src/ngx_http_lua_initworkerby.c +++ b/src/ngx_http_lua_initworkerby.c @@ -13,13 +13,8 @@ #include "ngx_http_lua_initworkerby.h" #include "ngx_http_lua_util.h" #include "ngx_http_lua_pipe.h" -#include "ngx_http_lua_event.h" -int ngx_http_lua_event_inited = 0; - -ngx_http_lua_event_actions_t ngx_http_lua_event_actions; - static u_char *ngx_http_lua_log_init_worker_error(ngx_log_t *log, u_char *buf, size_t len); @@ -51,10 +46,6 @@ ngx_http_lua_init_worker(ngx_cycle_t *cycle) return NGX_OK; } - if (ngx_http_lua_init_event(cycle) == NGX_OK) { - ngx_http_lua_event_inited = 1; - } - /* lmcf != NULL && lmcf->lua != NULL */ #if !(NGX_WIN32) diff --git a/src/ngx_http_lua_module.c b/src/ngx_http_lua_module.c index 09fd0a91f8..c72630ce16 100644 --- a/src/ngx_http_lua_module.c +++ b/src/ngx_http_lua_module.c @@ -32,6 +32,11 @@ #include "ngx_http_lua_ssl_session_fetchby.h" #include "ngx_http_lua_headers.h" #include "ngx_http_lua_pipe.h" +#include "ngx_http_lua_event.h" + +int ngx_http_lua_event_inited = 0; + +ngx_http_lua_event_actions_t ngx_http_lua_event_actions; static void *ngx_http_lua_create_main_conf(ngx_conf_t *cf); @@ -715,6 +720,24 @@ ngx_http_lua_init(ngx_conf_t *cf) ngx_http_lua_main_conf_t *lmcf; ngx_pool_cleanup_t *cln; ngx_str_t name = ngx_string("host"); + ngx_cycle_t *fake_cycle; + ngx_connection_t *c = NULL; + ngx_http_request_t *r = NULL; + ngx_uint_t i; + void *next; + ngx_event_t *rev, *wev; + ngx_http_lua_ctx_t *ctx; + ngx_module_t **modules; + ngx_http_module_t *module; + // ngx_core_module_t *c_module; + ngx_http_conf_ctx_t *conf_ctx, http_ctx; + void *cur, *prev; + ngx_conf_t conf; + ngx_http_lua_loc_conf_t *top_llcf; + ngx_http_core_loc_conf_t *top_clcf; + char *rv; + ngx_conf_file_t cf_file; + ngx_event_conf_t *ecf; if (ngx_process == NGX_PROCESS_SIGNALLER || ngx_test_config) { return NGX_OK; @@ -889,6 +912,246 @@ ngx_http_lua_init(ngx_conf_t *cf) ngx_http_lua_assert(lmcf->lua != NULL); + conf_ctx = cf->ctx; + http_ctx.main_conf = conf_ctx->main_conf; + + top_clcf = conf_ctx->loc_conf[ngx_http_core_module.ctx_index]; + top_llcf = conf_ctx->loc_conf[ngx_http_lua_module.ctx_index]; + + ngx_memzero(&conf, sizeof(ngx_conf_t)); + + conf.temp_pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, cf->log); + if (conf.temp_pool == NULL) { + return NGX_ERROR; + } + + conf.temp_pool->log = cf->log; + + /* we fake a temporary ngx_cycle_t here because some + * modules' merge conf handler may produce side effects in + * cf->cycle (like ngx_proxy vs cf->cycle->paths). + * also, we cannot allocate our temp cycle on the stack + * because some modules like ngx_http_core_module reference + * addresses within cf->cycle (i.e., via "&cf->cycle->new_log") + */ + fake_cycle = ngx_palloc(cf->pool, sizeof(ngx_cycle_t)); + if (fake_cycle == NULL) { + return NGX_ERROR; + } + + ngx_memcpy(fake_cycle, cf->cycle, sizeof(ngx_cycle_t)); + fake_cycle->pool = cf->pool; + + conf.ctx = &http_ctx; + conf.cycle = fake_cycle; + conf.pool = fake_cycle->pool; + conf.log = fake_cycle->log; + + ngx_memzero(&cf_file, sizeof(cf_file)); + cf_file.file.name = ngx_cycle->conf_file; + conf.conf_file = &cf_file; + + http_ctx.loc_conf = ngx_pcalloc(conf.pool, + sizeof(void *) * ngx_http_max_module); + if (http_ctx.loc_conf == NULL) { + return NGX_ERROR; + } + + http_ctx.srv_conf = ngx_pcalloc(conf.pool, + sizeof(void *) * ngx_http_max_module); + if (http_ctx.srv_conf == NULL) { + return NGX_ERROR; + } + + fake_cycle->log = cf->log; + fake_cycle->connection_n = 128; + + ngx_queue_init(&fake_cycle->reusable_connections_queue); + +#if (nginx_version >= 1009011) + modules = cf->cycle->modules; +#else + modules = ngx_modules; +#endif + +#if 0 + // init modules + for (i = 0; modules[i]; i++) { + if (modules[i]->init_module && modules[i]->type != NGX_CORE_MODULE) { + if (modules[i]->init_module(fake_cycle) != NGX_OK) { + return NGX_ERROR; + } + } + } +#endif + + ecf = ngx_palloc(fake_cycle->pool, sizeof(ngx_event_conf_t)); +#if 0 + // init ngx event + for (i = 0; modules[i]; i++) { + if (modules[i]->type != NGX_EVENT_MODULE) { + continue; + } + + c_module = modules[i]->ctx; + ecf->use = modules[i]->ctx_index; + ecf->name = c_module->name.data; + } +#endif + + // TODO: init fake_cycle->conf_ctx before assignment + fake_cycle->conf_ctx[ngx_events_module.index] = cf->ctx; + (fake_cycle->conf_ctx[ngx_events_module.index])[ngx_event_core_module.ctx_index] = (void **) ecf; + + fake_cycle->connections = ngx_alloc( + sizeof(ngx_connection_t) * fake_cycle->connection_n, + fake_cycle->log); + if (fake_cycle->connections == NULL) { + return NGX_ERROR; + } + + fake_cycle->read_events = ngx_alloc( + sizeof(ngx_event_t) * fake_cycle->connection_n, fake_cycle->log); + if (fake_cycle->read_events == NULL) { + return NGX_ERROR; + } + + rev = fake_cycle->read_events; + for (i = 0; i < fake_cycle->connection_n; i++) { + rev[i].closed = 1; + rev[i].instance = 1; + } + + fake_cycle->write_events = ngx_alloc( + sizeof(ngx_event_t) * fake_cycle->connection_n, fake_cycle->log); + if (fake_cycle->write_events == NULL) { + return NGX_ERROR; + } + + wev = fake_cycle->write_events; + for (i = 0; i < fake_cycle->connection_n; i++) { + wev[i].closed = 1; + } + + c = fake_cycle->connections; + i = fake_cycle->connection_n; + next = NULL; + + do { + i--; + + c[i].data = next; + c[i].read = &fake_cycle->read_events[i]; + c[i].write = &fake_cycle->write_events[i]; + c[i].fd = (ngx_socket_t) -1; + + next = &c[i]; + } while (i); + + fake_cycle->free_connections = next; + fake_cycle->free_connection_n = fake_cycle->connection_n; + + saved_cycle = ngx_cycle; + ngx_cycle = fake_cycle; + + c = ngx_http_lua_create_fake_connection(cf->pool); + if (c == NULL) { + return NGX_ERROR; + } + + r = ngx_http_lua_create_fake_request(c); + if (r == NULL) { + ngx_http_lua_close_fake_connection(c); + return NGX_ERROR; + } + + ngx_cycle = saved_cycle; + + for (i = 0; modules[i]; i++) { + if (modules[i]->type != NGX_HTTP_MODULE) { + continue; + } + + module = modules[i]->ctx; + + if (module->create_srv_conf) { + cur = module->create_srv_conf(&conf); + if (cur == NULL) { + return NGX_ERROR; + } + + http_ctx.srv_conf[modules[i]->ctx_index] = cur; + + if (module->merge_srv_conf) { + prev = module->create_srv_conf(&conf); + if (prev == NULL) { + return NGX_ERROR; + } + + rv = module->merge_srv_conf(&conf, prev, cur); + if (rv != NGX_CONF_OK) { + // goto failed; + return NGX_ERROR; + } + } + } + + if (module->create_loc_conf) { + cur = module->create_loc_conf(&conf); + if (cur == NULL) { + return NGX_ERROR; + } + + http_ctx.loc_conf[modules[i]->ctx_index] = cur; + + if (module->merge_loc_conf) { + if (modules[i] == &ngx_http_lua_module) { + prev = top_llcf; + + } else if (modules[i] == &ngx_http_core_module) { + prev = top_clcf; + + } else { + prev = module->create_loc_conf(&conf); + if (prev == NULL) { + return NGX_ERROR; + } + } + + rv = module->merge_loc_conf(&conf, prev, cur); + if (rv != NGX_CONF_OK) { + // goto failed; + return NGX_ERROR; + } + } + } + } + + ngx_destroy_pool(conf.temp_pool); + conf.temp_pool = NULL; + + r->main_conf = http_ctx.main_conf; + r->srv_conf = http_ctx.srv_conf; + r->loc_conf = http_ctx.loc_conf; + + ctx = ngx_http_lua_create_ctx(r); + if (ctx == NULL) { + ngx_http_lua_close_fake_connection(c); + return NGX_ERROR; + } + + ctx->context = NGX_HTTP_LUA_CONTEXT_INIT; + ctx->cur_co_ctx = NULL; + r->read_event_handler = ngx_http_block_reading; + + ngx_http_lua_set_req(lmcf->lua, r); + +#if 0 + if (ngx_http_lua_init_event(cf->cycle) == NGX_OK) { + ngx_http_lua_event_inited = 1; + } +#endif + if (!lmcf->requires_shm && lmcf->init_handler) { saved_cycle = ngx_cycle; ngx_cycle = cf->cycle; @@ -898,6 +1161,8 @@ ngx_http_lua_init(ngx_conf_t *cf) ngx_cycle = saved_cycle; if (rc != NGX_OK) { + // ngx_http_lua_close_fake_connection(c); + /* an error happened */ return NGX_ERROR; } diff --git a/src/ngx_http_lua_util.h b/src/ngx_http_lua_util.h index 46200f8977..1f00d8c8cd 100644 --- a/src/ngx_http_lua_util.h +++ b/src/ngx_http_lua_util.h @@ -40,7 +40,10 @@ | NGX_HTTP_LUA_CONTEXT_SSL_CERT \ | NGX_HTTP_LUA_CONTEXT_SSL_SESS_FETCH) -#define NGX_HTTP_LUA_CONTEXT_BLOCKED_COSOCKET (NGX_HTTP_LUA_CONTEXT_INIT_WORKER) +#define NGX_HTTP_LUA_CONTEXT_BLOCKED_COSOCKET \ + (NGX_HTTP_LUA_CONTEXT_INIT \ + |NGX_HTTP_LUA_CONTEXT_EXIT_WORKER) + #define NGX_HTTP_LUA_CONTEXT_COSOCKET (NGX_HTTP_LUA_CONTEXT_YIELDABLE \ | NGX_HTTP_LUA_CONTEXT_BLOCKED_COSOCKET) @@ -69,6 +72,7 @@ "ssl_session_store_by_lua*" \ : (c) == NGX_HTTP_LUA_CONTEXT_SSL_SESS_FETCH ? \ "ssl_session_fetch_by_lua*" \ + : (c) == NGX_HTTP_LUA_CONTEXT_INIT ? "init_by_lua*" \ : "(unknown)") diff --git a/t/058-tcp-socket.t b/t/058-tcp-socket.t index 65f4e41acc..6488b11db6 100644 --- a/t/058-tcp-socket.t +++ b/t/058-tcp-socket.t @@ -4372,7 +4372,7 @@ finish === TEST 73: run in init_worker_by_lua --- http_config - init_worker_by_lua_block { + init_by_lua_block { local sock = ngx.socket.tcp() local port = 80 local ok, err = sock:connect("agentzh.org", port) @@ -4428,3 +4428,4 @@ second line received: (?:Date|Server): .*? --- no_error_log [error] --- timeout: 10 +--- ONLY