问题1: 配置解析过程使用ngx_cycle->pool申请内存保存配置,结果造成野指针。

背景:需求开发过程,有一些结构需要在配置解析阶段保存,然后可以动态修改。看原来的代码配置解析都是使用cf->pool进行内存申请,但动态修改的过程显然拿不到cf,于是想到了一个全局的内存池ngx_cycle->pool,想当然的认为ngx_cycle的生命周期是从配置解析开始到进程退出,期间是不会释放ngx_cycle->pool的,但其实是错误的,具体原因如下:

nginx的启动源码简化后如下所示,从代码中的注释可以看出原来配置解析前后ngx_cycle变量中的pool不是同一个:

int ngx_cdecl
main(int argc, char *const *argv)
{
ngx_cycle_t *cycle, init_cycle;
...
ngx_memzero(&init_cycle, sizeof(ngx_cycle_t));
init_cycle.log = log;
ngx_cycle = &init_cycle;
...
//配置解析前创建的pool,解析过程拿到的ngx_cycle->pool就是这个
init_cycle.pool = ngx_create_pool(, log);
if (init_cycle.pool == NULL) {
return ;
}
...
cycle = ngx_init_cycle(&init_cycle);
if (cycle == NULL) {
if (ngx_test_config) {
ngx_log_stderr(, "configuration file %s test failed",
init_cycle.conf_file.data);
} return ;
}
...
ngx_cycle = cycle;
}

其中配置解析在ngx_init_cycle里面完成

ngx_cycle_t *
ngx_init_cycle(ngx_cycle_t *old_cycle)
{
ngx_cycle_t *cycle, **old;
...
log = old_cycle->log;
//这个pool放在cycle中带出去,配置解析之后赋值给ngx_cycle
pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, log);
if (pool == NULL) {
return NULL;
}
pool->log = log; cycle = ngx_pcalloc(pool, sizeof(ngx_cycle_t));
if (cycle == NULL) {
ngx_destroy_pool(pool);
return NULL;
} cycle->pool = pool;
cycle->log = log;
cycle->old_cycle = old_cycle;
.....
配置解析
...
return cycle;
}

结论:ngx_cycle的周期不能简单的认为是从进程启动到退出,其pool在配置解析前后是两个值。在配置处理阶段ngx_cycle表示的是老的cycle,启动阶段完成才会换成新的cycle,这也是为什么在启动阶段调用ngx_http_cycle_get_module_main_conf会把设备搞挂的原因。

问题2:检视代码的时候发现ngx_array_t如果想被反复使用的话,需要注意其内存池的唯一性,不然会内存泄漏。

直接上nginx内核源码

void
ngx_array_destroy(ngx_array_t *a)
{
ngx_pool_t *p; p = a->pool; if ((u_char *) a->elts + a->size * a->nalloc == p->d.last) {
p->d.last -= a->size * a->nalloc;
} if ((u_char *) a + sizeof(ngx_array_t) == p->d.last) {
p->d.last = (u_char *) a;
}
}

结论:如果一个nginx的动态数组想在使用过程中调用ngx_array_destroy销毁,然后再ngx_array_init重复利用的话,那么一定要保证这个数组的内存池只给他自己用,否则,ngx_array_destroy中的两个判断都不成立,内存池的这块内存将无法释放。

最新文章

  1. Confluent介绍(二)--confluent platform quickstart
  2. 时间就像Hourglass一样,积累(沉淀)越多,收获越大
  3. uva 10305 ordering tasks(超级烂题)——yhx
  4. js正则函数
  5. myeclipse 的 working set
  6. CentOS6.5安装配置Samba
  7. java中的final关键字
  8. 通过try、except和else的使用来使Python程序更加“强壮”
  9. 深入剖析Java中的装箱和拆箱(转)
  10. cmd 下登陆ftp及相关操作
  11. eclipse生成【带有外部jar包】的java可执行jar包
  12. C# String 与 StringBuilder
  13. 视频监控系统:C/S & B/S
  14. 守护进程的创建(syslog函数)
  15. 20145328 《网络对抗技术》逆向及Bof基础实践
  16. (Stanford CS224d) Deep Learning and NLP课程笔记(一):Deep NLP
  17. 【Leetcode】50. Pow(x, n)
  18. Swift教程之运算符
  19. iOS JSON字符串转化为字典-字典转Json字符串-
  20. kylin 连接 hortonworks 中的 hive 遇到的问题

热门文章

  1. 百度网盘SVIP不限速Mac破解版(亲测可用)
  2. 用户在浏览器输入URL或者跳转到一个URL后发生了什么
  3. 2Ubuntu学习
  4. hdu 5890 01背包 bitset
  5. 将pip源更换到国内镜像
  6. Nacos 快速开始
  7. 基于python3环境下搭建Robot Framework 自动化测试框架(一)
  8. 关于在IOS中 contenteditable=true 无法输入的问题
  9. hdu 4609: 3-idiots (FFT)
  10. postman-参数化