pgpool-II3.1 的内存泄漏(四)

本文涉及的产品
云原生数据库 PolarDB PostgreSQL 版,标准版 2核4GB 50GB
云原生数据库 PolarDB MySQL 版,通用型 2核8GB 50GB
简介:
磨砺技术珠矶,践行数据之道,追求卓越价值
回到上一级页面: PostgreSQL集群方案相关索引页     回到顶级页面:PostgreSQL索引页
[作者 高健@博客园  luckyjackgao@gmail.com]

 

接上文,继续对pgpool-II3.1的内存泄漏进行分析。

情形A extract_string 调用 strdup 

==27927== 3 bytes in 1 blocks are possibly lost in loss record 3 of 100
==27927== at 0x4A05E1C: malloc (vg_replace_malloc.c:195)
==27927== by 0x3C51E798C1: strdup (in /lib64/libc-2.5.so)
==27927== by 0x40C9C4: extract_string (pool_config.l:2065)
==27927== by 0x410D52: pool_get_config (pool_config.l:1756)
==27927== by 0x4066B5: main (main.c:320)
==27927== 

从上述log可知, 调用关系如下:
main->pool_get_config -> extract_string -> strdup->malloc

以下是各个函数的主要相关逻辑: 
pool_get_config函数(中间省略了很多):

复制代码
int pool_get_config(char *confpath, POOL_CONFIG_CONTEXT context){  
    ......                                
    #define PARSE_ERROR()  
           pool_error("pool_config: parse error at line %d '%s'", Lineno, yytext)                                              
    /* open config file */                                        
    fd = fopen(confpath, "r");                                        
    if (!fd){                                        
        fprintf(stderr, "pool_config: could not open configuration file (%s)\n", 
                POOL_CONF_FILE_NAME);                            
        fprintf(stderr, "pool_config: using default values...\n"); 
        return 0;                                    
    }                                        
                                            
    yyin = fd;                                        
    Lineno = 1;                                        
                                            
    for(;;)                                        
    {                                        
        token = yylex();                                    
        if (token == 0){                                    
            break;                                  
        }                                    
        if (token == POOL_PARSE_ERROR){                                    
            PARSE_ERROR();                                
            fclose(fd);                                
            return(-1);                                
        }                                    
        if (token == POOL_EOL)                                    
            continue;                                
                                            
        if (token != POOL_KEY){                                    
            PARSE_ERROR();                                
            fclose(fd);                                
            return(-1);                                
        }                                    
        ……                                    
                                            
        if (!strcmp(key, "allow_inet_domain_socket") && 
             CHECK_CONTEXT(INIT_CONFIG, context)){ 
            ……                                
        }                                    
        else if (!strcmp(key, "listen_addresses") && 
            CHECK_CONTEXT(INIT_CONFIG, context)){ 
            char *str;                     
            if (token != POOL_STRING && token != POOL_UNQUOTED_STRING && 
                   token != POOL_KEY){                                
                PARSE_ERROR();                            
                fclose(fd);                            
                return(-1);                            
            }                                
            str = extract_string(yytext, token);                                
            if (str == NULL){                                
                fclose(fd);                            
                return(-1);                            
            }                                
            pool_config->listen_addresses = str;                                
        }                                    
        ……                                  
        else if (!strncmp(key, "backend_hostname", 16) &&
                 CHECK_CONTEXT(INIT_CONFIG|RELOAD_CONFIG, context) && 
                 mypid == getpid()) 
                   /* this parameter must be modified by parent pid */                            
        {                                    
            int slot;                                
            char *str;                    
            slot = atoi(key + 16);                                
            if (slot < 0 || slot >= MAX_CONNECTION_SLOTS)
            {                                
                pool_error("pool_config: 
                     backend number %s for backend_hostname out of range", key);
                fclose(fd);                            
                return(-1);                            
            }                                
                                            
            str = extract_string(yytext, token);                                
            if (str == NULL){                                
                fclose(fd);                            
                return(-1);                            
            }                                
            if (context == INIT_CONFIG || (context == RELOAD_CONFIG && 
                 BACKEND_INFO(slot).backend_status == CON_UNUSED)) 
                strncpy(BACKEND_INFO(slot).backend_hostname, str,
                        MAX_DB_HOST_NAMELEN);                            
        }                                  
        ……                                    
        else if (!strcmp(key, "relcache_expire") &&
               CHECK_CONTEXT(INIT_CONFIG|RELOAD_CONFIG, context)){ 
            int v = atoi(yytext);          
            if (token != POOL_INTEGER || v < 0){                                
                pool_error("pool_config: %s 
                     must be equal or higher than 0 numeric value", key);                          fclose(fd);                            
                return(-1);                            
            }                                
            pool_config->relcache_expire = v;                                
        }                                 
    }                                        
                                            
    fclose(fd);                            
    ……                                        
    return 0;                                        
}                                            
复制代码
 extract_string 函数:

复制代码
static char *extract_string(char *value, POOL_TOKEN token){                        
    char *ret;          
    ret = strdup(value);                    
    if (!ret){                    
        pool_error("extract_string: out of memory");                
        return NULL;                
    }                    
                        
    if (token == POOL_STRING){                    
        ret[strlen(ret)-1] = '\0';                
        return (ret+1);                
    }                    
    return ret;                    
}
复制代码
strdup 是C 语言的标准函数, 是字符串复制。 
其内部调用了 malloc ,在运行结束的时候,应当释放。

但是!  
由于其 是在 pool_config.c 的 pool_get_config 中被调用,
这个函数 是要实现 把配置文件中的各项内容读取出来。
配置文件项内容的地址,就存储在 strdup 返回的 指针里面。

在pgpool 运行结束以前, 都是需要能随时访问 配置文件向内容的。
所以,在pgpool运行结束以前,都是不能随意 释放 strdup返回 值的。

至于运行结束的那一刻 是否 有代码专门来释放了,前面我们的分析已经说过,不在我们的讨论范围内。

 

[作者 高健@博客园  luckyjackgao@gmail.com]
回到上一级页面: PostgreSQL集群方案相关索引页     回到顶级页面:PostgreSQL索引页
磨砺技术珠矶,践行数据之道,追求卓越价值


本文转自健哥的数据花园博客园博客,原文链接:http://www.cnblogs.com/gaojian/archive/2012/08/21/2649037.html,如需转载请自行联系原作者
相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍如何基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
缓存 负载均衡 关系型数据库
Pgpool-II实现高可用+读写分离+负载均衡(一)---- 规划及安装
Pgpool-II是一款工作在PostgreSQL服务器和PostgreSQL数据库客户端之间的中间件。提供了连接池、复制、负载均衡、限制过多连接、看门狗、查询缓存等功能。
|
PHP 数据库 数据安全/隐私保护
|
存储 数据采集 安全
各种系统架构图与详细说明
原文:各种系统架构图与详细说明 共享平台逻辑架构设计 如上图所示为本次共享资源平台逻辑架构图,上图整体展现说明包括以下几个方面: 1 应用系统建设 本次项目的一项重点就是实现原有应用系统的全面升级以及新的应用系统的开发,从而建立行业的全面的应用系统架构群。
26435 1
|
5月前
|
搜索推荐 测试技术 C语言
NPU适配推荐系统GR模型流程
本示例将开源Generative Recommendations模型迁移至NPU训练,并通过HSTU融合算子优化性能。基于Atlas 800T A2平台,使用PyTorch 2.1.0、Python 3.11.0等环境。文档涵盖容器启动、依赖安装、算子适配、源码修改、数据预处理及配置文件设置等内容。性能测试显示,使用HSTU融合算子可显著降低端到端耗时(如ml_1m数据集单step从346ms降至47.6ms)。
|
应用服务中间件 Go nginx
K8S Ingress Controller 健康检查原理剖析
K8S本身提供了Liveness和Readiness机制对Pod进行健康监控,同样我们在部署K8S Ingress Controller时也配置了LivenessProbe和ReadinessProbe来对其进行健康检查,本文旨在剖析Nginx Ingress Controller内部的健康检查逻辑,以便于更好地监控Nginx Ingress Controller。
9356 0
|
10月前
|
机器学习/深度学习 人工智能 PyTorch
使用PyTorch实现GPT-2直接偏好优化训练:DPO方法改进及其与监督微调的效果对比
本文将系统阐述DPO的工作原理、实现机制,以及其与传统RLHF和SFT方法的本质区别。
641 22
使用PyTorch实现GPT-2直接偏好优化训练:DPO方法改进及其与监督微调的效果对比
|
11月前
|
运维 JavaScript jenkins
鸿蒙5.0版开发:分析CppCrash(进程崩溃)
在HarmonyOS 5.0中,CppCrash指C/C++运行时崩溃,常见原因包括空指针、数组越界等。系统提供基于posix信号机制的异常检测能力,生成详细日志辅助定位。本文详解CppCrash分析方法,涵盖异常检测、问题定位思路及案例分析。
363 4
|
12月前
|
JSON 算法 Java
hutool工具的简单使用
这篇文章介绍了Hutool工具库的基本使用,通过代码示例展示了如何利用Hutool进行字符串处理、文件操作、集合操作、加密解密、日期时间处理、网络请求和读取资源文件等常见任务。
403 0
hutool工具的简单使用
|
存储 Kubernetes 监控
在K8S中,Resource Quotas是什么?如何做资源管理的?
在K8S中,Resource Quotas是什么?如何做资源管理的?