磨砺技术珠矶,践行数据之道,追求卓越价值
回到上一级页面: PostgreSQL集群方案相关索引页     回到顶级页面:PostgreSQL索引页
[作者 高健@博客园  luckyjackgao@gmail.com]
情形B read_startup_packet 调用 calloc 
==27927== 594 (528 direct, 66 indirect) bytes in 11 blocks are definitely lost in loss record 85 of 100
==27927== at 0x4A05140: calloc (vg_replace_malloc.c:418)
==27927== by 0x40895B: read_startup_packet (child.c:803)
==27927== by 0x409663: do_child (child.c:210)
==27927== by 0x403F04: fork_a_child (main.c:1073)
==27927== by 0x406C00: main (main.c:550)
从上述log可知, 调用关系如下:
main-> fork_a_child -> do_child -> read_startup_packet -> calloc
以下是各个函数的主要相关逻辑:
main函数:
复制代码
/*                                
* pgpool main program                                
*/                                
int main(int argc, char **argv)                                
{                                
……                            
/*                            
* We need to block signal here. Otherwise child might send some  
* signals, for example SIGUSR1(fail over).  Children will inherit
* signal blocking but they do unblock signals at the very beginning 
* of process.  So this is harmless.                            
*/                            
POOL_SETMASK(&BlockSig);                            
/* fork the children */                            
for (i=0;i<pool_config->num_init_children;i++)                            
{                            
process_info[i].pid = fork_a_child(unix_fd, inet_fd, i);                        
process_info[i].start_time = time(NULL);                        
}                            
/* set up signal handlers */                            
pool_signal(SIGTERM, exit_handler);                            
pool_signal(SIGINT, exit_handler);                            
pool_signal(SIGQUIT, exit_handler);                            
pool_signal(SIGCHLD, reap_handler);                            
pool_signal(SIGUSR1, failover_handler);                            
pool_signal(SIGUSR2, wakeup_handler);                            
pool_signal(SIGHUP, reload_config_handler);                            
/* create pipe for delivering event */                            
if (pipe(pipe_fds) < 0)                            
{                            
pool_error("failed to create pipe");                        
myexit(1);                        
}                            
……                            
/*                            
* This is the main loop                            
*/                            
for (;;)                            
{                            
……                        
}                            
pool_shmem_exit(0);                            
}
复制代码
for_a_child函数:
复制代码
/*                            
* fork a child                            
*/                            
pid_t fork_a_child(int unix_fd, int inet_fd, int id)                            
{                            
pid_t pid;                        
pid = fork();                        
if (pid == 0)                        
{                        
/* Before we unconditionally closed pipe_fds[0] and pipe_fds[1] 
* here, which is apparently wrong since in the start up of 
* pgpool, pipe(2) is not called yet and it mistakenly closes  
* fd 0. Now we check the fd > 0 before close(), expecting  
* pipe returns fds greater than 0.  Note that we cannot 
* unconditionally remove close(2) calls since fork_a_child() 
* may be called *after* pgpool starting up.                    
*/                    
if (pipe_fds[0] > 0)                    
{                    
close(pipe_fds[0]);                
close(pipe_fds[1]);                
}                    
myargv = save_ps_display_args(myargc, myargv);                    
/* call child main */                    
POOL_SETMASK(&UnBlockSig);                    
reload_config_request = 0;                    
my_proc_id = id;                    
run_as_pcp_child = false;                    
do_child(unix_fd, inet_fd);                    
}                        
else if (pid == -1)                        
{                        
pool_error("fork() failed. reason: %s", strerror(errno));                    
myexit(1);                    
}                        
return pid;                        
}
复制代码
do_child函数:
复制代码
/*                                        
* child main loop                                        
*/                                        
void do_child(int unix_fd, int inet_fd)                                        
{                                        
……                                    
for (;;){                                  
StartupPacket *sp;                                
……                             
/* perform accept() */                                
frontend = do_accept(unix_fd, inet_fd, &timeout);
……                                
/* read the startup packet */                                
retry_startup:                                
sp = read_startup_packet(frontend);                                
if (sp == NULL){                                
/* failed to read the startup packet. return to the accept() loop */ 
pool_close(frontend);                            
connection_count_down();                            
continue;                            
}                                
……                                
/*                                
* Ok, negotiaton with frontend has been done. Let's go to the
* next step.  Connect to backend if there's no existing 
* connection which can be reused by this frontend.
* Authentication is also done in this step. 
*/                                
……                                
/* query process loop */                                
for (;;){                                
……                            
}                                
/* Destroy session context */                                
pool_session_context_destroy();                                
/* Mark this connection pool is not conncted from frontend */ 
pool_coninfo_unset_frontend_connected
(pool_get_process_context()->proc_id, pool_pool_index());
accepted = 0;                                
connection_count_down();       
timeout.tv_sec = pool_config->child_life_time; 
timeout.tv_usec = 0;                                
/* increment queries counter if necessary */ 
if ( pool_config->child_max_connections > 0 ) 
connections_count++;                            
/* check if maximum connections count for this child reached */ 
if ( ( pool_config->child_max_connections > 0 ) && 
( connections_count >= pool_config->child_max_connections ) ){
pool_log("child exiting, %d connections reached", 
pool_config->child_max_connections);                            
send_frontend_exits();                            
child_exit(2);                            
}                                
}                                    
child_exit(0);                                    
}
复制代码
read_startup_packet 函数:
复制代码
/*                                    
* Read startup packet                                    
*                                    
* Read the startup packet and parse the contents.                                    
*/                                    
static StartupPacket *read_startup_packet(POOL_CONNECTION *cp)                                    
{                                    
StartupPacket *sp;                                
……                                
sp = (StartupPacket *)calloc(sizeof(*sp), 1);                                
if (!sp)                                
{                                
pool_error("read_startup_packet: out of memory");                            
return NULL;                            
}                                
……                                
sp->startup_packet = calloc(len, 1);                                
if (!sp->startup_packet)                                
{                                
pool_error("read_startup_packet: out of memory");                            
pool_free_startup_packet(sp);                            
alarm(0);                            
pool_signal(SIGALRM, SIG_IGN);                            
return NULL;                            
}                                
……                                
switch(sp->major)                                
{                                
case PROTO_MAJOR_V2: /* V2 */                            
sp2 = (StartupPacket_v2 *)(sp->startup_packet);                        
sp->database = calloc(SM_DATABASE+1, 1);                        
if (!sp->database)                        
{                        
pool_error("read_startup_packet: out of memory");                    
pool_free_startup_packet(sp);                    
alarm(0);                    
pool_signal(SIGALRM, SIG_IGN);                    
return NULL;                    
}                        
……                        
break;                 
case 1234:        /* cancel or SSL request */                    
/* set dummy database, user info */                        
sp->database = calloc(1, 1);                        
if (!sp->database)                        
{                        
pool_error("read_startup_packet: out of memory");                    
pool_free_startup_packet(sp);                    
alarm(0);                    
pool_signal(SIGALRM, SIG_IGN);                    
return NULL;                    
}                        
sp->user = calloc(1, 1);                        
if (!sp->user)                        
{                        
pool_error("read_startup_packet: out of memory");                    
pool_free_startup_packet(sp);                    
alarm(0);                    
pool_signal(SIGALRM, SIG_IGN);                    
return NULL;                    
}                        
break;                        
default:                            
pool_error("read_startup_packet: invalid major no: %d", sp->major);                        
pool_free_startup_packet(sp);                        
alarm(0);                        
pool_signal(SIGALRM, SIG_IGN);                        
return NULL;                        
}                                
pool_debug("Protocol Major: %d Minor: %d database: %s user: %s",  
sp->major, sp->minor, sp->database, sp->user);                        
alarm(0);                                
pool_signal(SIGALRM, SIG_IGN);                                
return sp;                                
}                                    
复制代码
由以上各个函数的逻辑,可以看到 
在 read_startup_packet 函数中,调用 calloc 来开了内存。
但是在do_child 函数的主循环中,会反复使用 read_startup_packet 函数,并且也未能释放内存。 
由于 do_child 函数的反复循环,就会反复开内存而不释放。
这里确确实实地 发生了 内存泄露。
其实,它的do_child函数的循环的末尾,应该释放 StartupPacket *sp 才好,不知为何不去释放。
[作者 高健@博客园  luckyjackgao@gmail.com]
回到上一级页面: PostgreSQL集群方案相关索引页     回到顶级页面:PostgreSQL索引页
磨砺技术珠矶,践行数据之道,追求卓越价值
本文转自健哥的数据花园博客园博客,原文链接:http://www.cnblogs.com/gaojian/archive/2012/08/21/2649065.html,如需转载请自行联系原作者

pgpool-II3.1 的内存泄漏(五)相关推荐

  1. 解析面试常问题之JavaScript中的闭包概念及应用,顺便普及一下大家口中常说的内存泄漏问题

    JavaScript中的闭包是一个面试中经常被考到的问题,大家可能都对这个概念多多少少都有一些模糊的概念或者一点都不了解,那么今天就来给大家讲解一下. 公众号:前端印象 不定时有送书活动,记得关注~ ...

  2. Android开发笔记(七十五)内存泄漏的处理

    内存泄漏的原因 一直以来以为只有C/C++才存在内存泄漏的问题,没想到拥有内存回收机制的Java也可能出现内存泄漏.C/C++存在指针的概念,程序中需要使用指针变量时,就从内存中开辟一块区域,并把该区 ...

  3. android释放acitity内存,Android 内存泄漏分析与解决方法

    在分析Android内存泄漏之前,先了解一下JAVA的一些知识 1. JAVA中的对象的创建 使用new指令生成对象时,堆内存将会为此开辟一份空间存放该对象 垃圾回收器回收非存活的对象,并释放对应的内 ...

  4. 内存泄漏和内存溢出的关系和区别

    作者:不怕天黑_0819 链接:https://www.jianshu.com/p/61d34df7eabe 一.内存泄漏(memory leak) 1.内存泄漏是指程序中已动态分配的堆内存由于某种原 ...

  5. JavaScript内存泄漏

    内存泄漏简介 内存泄漏(Memory Leak)是指程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果. 内存泄漏缺陷具有隐蔽性. ...

  6. nstimer循环引用_解决NSTimer循环引用导致内存泄漏的六种方法

    demo放在了GitHub 内存泄漏的原因: self强引用timer.timer添加在runloop上,只要timer不销毁self就销毁不了.当然了你可以选择在viewWillDisappear中 ...

  7. 5 个 Android 开发中比较常见的内存泄漏问题及解决办法

    Android开发中,内存泄漏是比较常见的问题,有过一些Android编程经历的童鞋应该都遇到过,但为什么会出现内存泄漏呢?内存泄漏又有什么影响呢? 在Android程序开发中,当一个对象已经不需要再 ...

  8. Handler消息机制(八):Handler内存泄漏的场景有哪些,如何避免

    使用AndroidStudio检测内存泄漏: 一.内存泄漏的原因 一般内存泄漏(traditional memory leak)的原因是:由忘记释放分配的内存导致的. 逻辑内存泄漏(logical m ...

  9. VC使用CRT调试功能来检测内存泄漏

    信息来源:csdn      C/C++ 编程语言的最强大功能之一便是其动态分配和释放内存,但是中国有句古话:"最大的长处也可能成为最大的弱点",那么 C/C++ 应用程序正好印证 ...

  10. linux c 内存泄漏调试工具 《valgrind用户手册》 2. 使用和理解Valgrind核心

    valgrind 用户手册原版地址:https://valgrind.org/docs/manual/manual.html 此原文地址:https://valgrind.org/docs/manua ...

最新文章

  1. 疯狂python讲义视频 百度云-每周一书《疯狂Python讲义》分享!
  2. linux 如何运行r脚本,Linux系统下如何debug R脚本
  3. JQuery对selecte中的元素的操作
  4. SQL Editor and reconnect【mysql(workbench)更新数据时候的一个异常】【Error Code:1175】
  5. OS- -内存之虚拟内存
  6. 图像的全局特征--HOG特征、DPM特征
  7. rdb和aof到底哪个快
  8. SpringBoot RequestBody ajax提交对象
  9. 挑战10个最难的Java面试题(附答案)【下】
  10. Eclipse 项目导入 Android Studio 导致的乱码问题解决
  11. Hive-3.1.3安装配置运行
  12. 一个端到端的机器学习项目全纪录(加州房价预测)
  13. 2016北航计算机学院研究生院,北京航空航天大学2016年计算机考研分数线_北京航空航天大学考研复试分数线...
  14. 基于IDS模型设计的ICS
  15. 企业数字化最核心的数据智能,它的价值到底在哪?
  16. 广东省数字经济行业发展动态及十四五前景预测分析报告2022-2027年
  17. HDU 6194 string string string (后缀数组+线段树)
  18. 传播知识,分享快乐--我的相关资源下载(不定期更新)
  19. 不是python内置函数的是_Python内置函数
  20. 使用Qt创建一个时钟

热门文章

  1. Set,Map数据结构
  2. 关于百度地图根据经纬度获取城市信息的接口
  3. Coding theano under remote ubuntu server from local Mac (在本地mac机器上,写、跑、调试、看-远程ubuntu上的theano代码)...
  4. Castle ActiveRecord学习实践(1)入门
  5. Bret Victor(苹果 UI 设计师):互动的未来不应只在手指上
  6. 【Music】Never took the time
  7. 虚拟环境mkvirtualenv
  8. 第4章 类与对象 枚举类
  9. python包/模块路径
  10. 结构等待队列[网络编程]select流程分析