lua-module
struct ngx_module_s {
ngx_uint_t ctx_index;
ngx_uint_t index;
char *name;
ngx_uint_t spare0;
ngx_uint_t spare1;
ngx_uint_t version;
const char *signature;
void *ctx;
ngx_command_t *commands;
ngx_uint_t type;
ngx_int_t (*init_master)(ngx_log_t *log);
ngx_int_t (*init_module)(ngx_cycle_t *cycle);
ngx_int_t (*init_process)(ngx_cycle_t *cycle);
ngx_int_t (*init_thread)(ngx_cycle_t *cycle);
void (*exit_thread)(ngx_cycle_t *cycle);
void (*exit_process)(ngx_cycle_t *cycle);
void (*exit_master)(ngx_cycle_t *cycle);
uintptr_t spare_hook0;
uintptr_t spare_hook1;
uintptr_t spare_hook2;
uintptr_t spare_hook3;
uintptr_t spare_hook4;
uintptr_t spare_hook5;
uintptr_t spare_hook6;
uintptr_t spare_hook7;
};
#define NGX_MODULE_V1 \
NGX_MODULE_UNSET_INDEX, NGX_MODULE_UNSET_INDEX, \
NULL, 0, 0, nginx_version, NGX_MODULE_SIGNATURE
ngx_module_t ngx_http_lua_module = {
NGX_MODULE_V1,
&ngx_http_lua_module_ctx, /* module context */
ngx_http_lua_cmds, /* module directives */
NGX_HTTP_MODULE, /* module type */
NULL, /* init master */
NULL, /* init module */
ngx_http_lua_init_worker, /* init process */
NULL, /* init thread */
NULL, /* exit thread */
NULL, /* exit process */
NULL, /* exit master */
NGX_MODULE_V1_PADDING
};
// http模块的函数表,在配置解析阶段被框架调用
typedef struct {
// ngx_http_block里,创建配置结构体后,开始解析之前调用
// 常用于添加变量定义
ngx_int_t (*preconfiguration)(ngx_conf_t *cf);
// ngx_http_block里,解析、合并完配置后调用
// 常用于初始化模块的phases handler
ngx_int_t (*postconfiguration)(ngx_conf_t *cf);
// 创建模块的main配置,只有一个,在http main域
void *(*create_main_conf)(ngx_conf_t *cf);
// 初始化模块的main配置,只有一个,在http main域
char *(*init_main_conf)(ngx_conf_t *cf, void *conf);
// 创建、合并模块的srv配置
void *(*create_srv_conf)(ngx_conf_t *cf);
char *(*merge_srv_conf)(ngx_conf_t *cf, void *prev, void *conf);
// 创建、合并模块的location配置
void *(*create_loc_conf)(ngx_conf_t *cf);
char *(*merge_loc_conf)(ngx_conf_t *cf, void *prev, void *conf);
} ngx_http_module_t;
ngx_worker_process_init代码里调用【cycle->modules[i]->init_process(cycle)】
初始化进程:
for (i = 0; cycle->modules[i]; i++) {
if (cycle->modules[i]->init_process) {
if (cycle->modules[i]->init_process(cycle) == NGX_ERROR) {
/* fatal */
exit(2);
}
}
}
ngx_int_t
ngx_http_lua_init_worker(ngx_cycle_t *cycle)
{
char *rv;
void *cur, *prev;
ngx_uint_t i;
ngx_conf_t conf;
ngx_cycle_t *fake_cycle;
ngx_module_t **modules;
ngx_open_file_t *file, *ofile;
ngx_list_part_t *part;
ngx_connection_t *c = NULL;
ngx_http_module_t *module;
ngx_http_request_t *r = NULL;
ngx_http_lua_ctx_t *ctx;
ngx_http_conf_ctx_t *conf_ctx, http_ctx;
ngx_http_lua_loc_conf_t *top_llcf;
ngx_http_lua_main_conf_t *lmcf;
ngx_http_core_loc_conf_t *clcf, *top_clcf;
lmcf = ngx_http_cycle_get_module_main_conf(cycle, ngx_http_lua_module);
if (lmcf == NULL || lmcf->lua == NULL) {
return NGX_OK;
}
/* lmcf != NULL && lmcf->lua != NULL */
#if !(NGX_WIN32)
if (ngx_process == NGX_PROCESS_HELPER
# ifdef HAVE_PRIVILEGED_PROCESS_PATCH
&& !ngx_is_privileged_agent
# endif
)
{
/* disable init_worker_by_lua* and destroy lua VM in cache processes */
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
"lua close the global Lua VM %p in the "
"cache helper process %P", lmcf->lua, ngx_pid);
lmcf->vm_cleanup->handler(lmcf->vm_cleanup->data);
lmcf->vm_cleanup->handler = NULL;
return NGX_OK;
}
#endif /* NGX_WIN32 */
if (lmcf->init_worker_handler == NULL) {
return NGX_OK;
}
conf_ctx = (ngx_http_conf_ctx_t *) cycle->conf_ctx[ngx_http_module.index];
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, cycle->log);
if (conf.temp_pool == NULL) {
return NGX_ERROR;
}
conf.temp_pool->log = cycle->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(cycle->pool, sizeof(ngx_cycle_t));
if (fake_cycle == NULL) {
goto failed;
}
ngx_memcpy(fake_cycle, cycle, sizeof(ngx_cycle_t));
#if defined(nginx_version) && nginx_version >= 9007
ngx_queue_init(&fake_cycle->reusable_connections_queue);
#endif
if (ngx_array_init(&fake_cycle->listening, cycle->pool,
cycle->listening.nelts || 1,
sizeof(ngx_listening_t))
!= NGX_OK)
{
goto failed;
}
#if defined(nginx_version) && nginx_version >= 1003007
if (ngx_array_init(&fake_cycle->paths, cycle->pool, cycle->paths.nelts || 1,
sizeof(ngx_path_t *))
!= NGX_OK)
{
goto failed;
}
#endif
part = &cycle->open_files.part;
ofile = part->elts;
if (ngx_list_init(&fake_cycle->open_files, cycle->pool, part->nelts || 1,
sizeof(ngx_open_file_t))
!= NGX_OK)
{
goto failed;
}
for (i = 0; /* void */ ; i++) {
if (i >= part->nelts) {
if (part->next == NULL) {
break;
}
part = part->next;
ofile = part->elts;
i = 0;
}
file = ngx_list_push(&fake_cycle->open_files);
if (file == NULL) {
goto failed;
}
ngx_memcpy(file, ofile, sizeof(ngx_open_file_t));
}
if (ngx_list_init(&fake_cycle->shared_memory, cycle->pool, 1,
sizeof(ngx_shm_zone_t))
!= NGX_OK)
{
goto failed;
}
conf.ctx = &http_ctx;
conf.cycle = fake_cycle;
conf.pool = fake_cycle->pool;
conf.log = cycle->log;
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;
}
#if defined(nginx_version) && nginx_version >= 1009011
modules = cycle->modules;
#else
modules = ngx_modules;
#endif
for (i = 0; modules[i]; i++) {
if (modules[i]->type != NGX_HTTP_MODULE) {
continue;
}
module = modules[i]->ctx;
if (module->create_srv_conf) {
/* 这里的module的类型是ngx_http_module_t,
create_srv_conf函数指针指向的函数的作用
是创建模块的main配置,只有一个,在http main域
*/
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;
}
}
}
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;
}
}
}
}
ngx_destroy_pool(conf.temp_pool);
conf.temp_pool = NULL;
c = ngx_http_lua_create_fake_connection(NULL);
if (c == NULL) {
goto failed;
}
c->log->handler = ngx_http_lua_log_init_worker_error;
r = ngx_http_lua_create_fake_request(c);
if (r == NULL) {
goto failed;
}
r->main_conf = http_ctx.main_conf;
r->srv_conf = http_ctx.srv_conf;
r->loc_conf = http_ctx.loc_conf;
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
#if defined(nginx_version) && nginx_version >= 1003014
# if nginx_version >= 1009000
ngx_set_connection_log(r->connection, clcf->error_log);
# else
ngx_http_set_connection_log(r->connection, clcf->error_log);
# endif
#else
c->log->file = clcf->error_log->file;
if (!(c->log->log_level & NGX_LOG_DEBUG_CONNECTION)) {
c->log->log_level = clcf->error_log->log_level;
}
#endif
ctx = ngx_http_lua_create_ctx(r);
if (ctx == NULL) {
goto failed;
}
ctx->context = NGX_HTTP_LUA_CONTEXT_INIT_WORKER;
ctx->cur_co_ctx = NULL;
r->read_event_handler = ngx_http_block_reading;
ngx_http_lua_set_req(lmcf->lua, r);
(void) lmcf->init_worker_handler(cycle->log, lmcf, lmcf->lua);
ngx_destroy_pool(c->pool);
return NGX_OK;
failed:
if (conf.temp_pool) {
ngx_destroy_pool(conf.temp_pool);
}
if (c) {
ngx_http_lua_close_fake_connection(c);
}
return NGX_ERROR;
}
static void *
ngx_http_core_create_srv_conf(ngx_conf_t *cf)
{
ngx_http_core_srv_conf_t *cscf;
cscf = ngx_pcalloc(cf->pool, sizeof(ngx_http_core_srv_conf_t));
if (cscf == NULL) {
return NULL;
}
/*
* set by ngx_pcalloc():
*
* conf->client_large_buffers.num = 0;
*/
if (ngx_array_init(&cscf->server_names, cf->temp_pool, 4,
sizeof(ngx_http_server_name_t))
!= NGX_OK)
{
return NULL;
}
cscf->connection_pool_size = NGX_CONF_UNSET_SIZE;
cscf->request_pool_size = NGX_CONF_UNSET_SIZE;
cscf->client_header_timeout = NGX_CONF_UNSET_MSEC;
cscf->client_header_buffer_size = NGX_CONF_UNSET_SIZE;
cscf->ignore_invalid_headers = NGX_CONF_UNSET;
cscf->merge_slashes = NGX_CONF_UNSET;
cscf->underscores_in_headers = NGX_CONF_UNSET;
cscf->file_name = cf->conf_file->file.name.data;
cscf->line = cf->conf_file->line;
return cscf;
}
[root@localhost sbin]# gdb agw_engine core.753
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-120.el7
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
...
Reading symbols from /agw/sbin/agw_engine...done.
[New LWP 753]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
Core was generated by `nginx: master process /agw/sbin/agw_engine -c /agw/conf/engine/163'.
Program terminated with signal 11, Segmentation fault.
#0 0x0000000000480a6a in ngx_http_core_create_srv_conf (cf=0x7fff9f0a8c90) at src/http/ngx_http_core_module.c:3377
3377 src/http/ngx_http_core_module.c: 没有那个文件或目录.
Missing separate debuginfos, use: debuginfo-install glibc-2.17-326.el7_9.x86_64 libgcc-4.8.5-44.el7.x86_64 nss-softokn-freebl-3.36.0-5.el7_5.x86_64 zlib-1.2.7-21.el7_9.x86_64
(gdb) where
#0 0x0000000000480a6a in ngx_http_core_create_srv_conf (cf=0x7fff9f0a8c90) at src/http/ngx_http_core_module.c:3377
#1 0x0000000000500e47 in ngx_http_lua_init_worker (cycle=0x13a1ae0) at ./src/luam/src/ngx_http_lua_initworkerby.c:195
#2 0x0000000000470699 in ngx_worker_process_init (cycle=cycle@entry=0x13a1ae0, worker=) at src/os/unix/ngx_process_cycle.c:902
#3 0x0000000000470b51 in ngx_worker_process_cycle (cycle=0x13a1ae0, data=) at src/os/unix/ngx_process_cycle.c:706
#4 0x000000000046f3e2 in ngx_spawn_process (cycle=cycle@entry=0x13a1ae0, proc=0x470b31 , data=0x0, name=0x671c23 "worker process",
respawn=respawn@entry=0) at src/os/unix/ngx_process.c:199
#5 0x0000000000471510 in ngx_reap_children (cycle=0x13a1ae0) at src/os/unix/ngx_process_cycle.c:598
#6 ngx_master_process_cycle (cycle=cycle@entry=0x13a1ae0) at src/os/unix/ngx_process_cycle.c:174
#7 0x000000000044b13a in main (argc=, argv=) at src/core/nginx.c:383
(gdb) quit