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

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

接上文,

情形D extract_string_tokens 调用 malloc 

==27927== 24,630 (24,576 direct, 54 indirect) bytes in 3 blocks are definitely lost in loss record 100 of 100
==27927== at 0x4A05E1C: malloc (vg_replace_malloc.c:195)
==27927== by 0x40C8FC: extract_string_tokens (pool_config.l:2191)
==27927== by 0x41177B: pool_get_config (pool_config.l:1657)
==27927== by 0x4066B5: main (main.c:320)
==27927== 

从上述log可知, 调用关系如下:

main->pool_get_config -> extract_string_tokens -> malloc

以下是各个函数的主要相关逻辑:

pool_get_config 函数:

复制代码
int pool_get_config(char *confpath, POOL_CONFIG_CONTEXT context)                                                
{                                                
    FILE *fd;                                            
    int token;                                            
    char key[1024];                                            
    double total_weight;                                            
    int i;                                            
    bool log_destination_changed = false; 
                                                
    #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, "reset_query_list") && 
                 CHECK_CONTEXT(INIT_CONFIG|RELOAD_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->reset_query_list = extract_string_tokens(str, ";",                            pool_config->num_reset_queries); 
            if (pool_config->reset_query_list == NULL)                                    
            {                                    
                fclose(fd);                                
                return(-1);                                
            }                                    
        }                                        
                                                
        else if (!strcmp(key, "white_function_list") && 
                 CHECK_CONTEXT(INIT_CONFIG|RELOAD_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->white_function_list =                                    
                extract_string_tokens(str, ",", 
                   &pool_config->num_white_function_list); 
                                                
            if (pool_config->white_function_list == NULL)
            {                                    
                fclose(fd);                                
                return(-1);                                
            }                                    
            for (i=0;i<pool_config->num_white_function_list;i++)
            {                                    
                add_regex_pattern("white_function_list",
                   pool_config->white_function_list[i]);                                
            }                                    
        }                                        
                                                
        else if (!strcmp(key, "black_function_list") && 
                 CHECK_CONTEXT(INIT_CONFIG|RELOAD_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->black_function_list =                                    
                extract_string_tokens(str, ",", 
                    &pool_config->num_black_function_list); 
                                                
            if (pool_config->black_function_list == NULL)
            {                                    
                fclose(fd);                                
                return(-1);                                
            }                                    
            for (i=0;i<pool_config->num_black_function_list;i++)                                    
            {                                    
                add_regex_pattern("black_function_list", 
                    pool_config->black_function_list[i]); 
            }                                    
        }                                        
        ……                                        
        else if (!strncmp(key, "backend_flag", 12) && 
                 CHECK_CONTEXT(INIT_CONFIG|RELOAD_CONFIG, context) &&                                
                 mypid == getpid()) 
                  /* this parameter must be modified by parent pid */                                
        {                                        
            ……                                    
            flags = extract_string_tokens(str, "|", &n);
            if (!flags || n < 0)                                    
            {                                    
                pool_debug("pool_config: unable to get backend flags");                                
                fclose(fd);                                
                return(-1);                                
            }                                    
                                                
            for (i=0;i<n;i++)                                    
            {                                    
                if (!strcmp(flags[i], "ALLOW_TO_FAILOVER")) 
                {                                
                    if (disallow_to_failover_is_specified)
                    {                            
                        pool_error("pool_config: cannot set ALLOW_TO_FAILOVER 
                          and DISALLOW_TO_FAILOVER at the same time");                        
                        fclose(fd);                        
                        return(-1);                        
                    }                            
                    flag &= ~POOL_FAILOVER;                            
                    allow_to_failover_is_specified = true;                            
                    pool_debug("pool_config: allow_to_failover on"); 
                }                                
                                                
                else if (!strcmp(flags[i], "DISALLOW_TO_FAILOVER")) 
                {                                
                    if (allow_to_failover_is_specified)                            
                    {                            
                        pool_error("pool_config: cannot set ALLOW_TO_FAILOVER 
                            and DISALLOW_TO_FAILOVER at the same time"); 
                        fclose(fd);                        
                        return(-1);                        
                    }                            
                    flag |= POOL_FAILOVER;                            
                    disallow_to_failover_is_specified = true;                            
                    pool_debug("pool_config: disallow_to_failover on");                            
                }                                
                                                
                else                                
                {                                
                    pool_error("pool_config: invalid backend flag:%s", flags[i]);                            
                }                                
            }                                    
            ……                                    
        }                                        
                                                
        ……                                        
    }                                            
                                                
    fclose(fd);                                            
                                                
    ……                                            
    return 0;                                            
}                                                
                                            
复制代码
extract_string_tokens 函数:

复制代码
/*                                        
 * Extract tokens separated by delimi from str. Return value is an 
 * array of pointers to malloced strings. number of tokens is set to 
 * n; note that str will be destroyed by strtok(). 
 */                                        
#define MAXTOKENS 1024                                        
static char **extract_string_tokens(char *str, char *delimi, int *n)                                        
{                                        
    char *token;                                    
    static char **tokens;                                    
                                        
    *n = 0;                                    
                                        
    tokens = malloc(MAXTOKENS*sizeof(char *));                                    
    if (tokens == NULL)                                    
    {                                    
        pool_error("extract_string_tokens: out of memory");                                
        return NULL;                                
    }                                    
                                        
    for (token = strtok(str, delimi); token != NULL && *n < MAXTOKENS; token = strtok(NULL, delimi))                                    
    {                                    
        tokens[*n] = strdup(token);                                
        if (tokens[*n] == NULL)                                
        {                                
            pool_error("extract_string_tokens: out of memory");                            
            return NULL;                            
        }                                
        pool_debug("extract_string_tokens: token: %s", tokens[*n]);                                
        (*n)++;                                
    }                                    
    return tokens;                                    
}                                        
                                        
复制代码
和情形 A 有些类似,在 extract_string_tokens函数中,调用了 malloc开了内存 

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

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

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

其实,如果略作展开,看pgpool运行结束的时候,是否有可能释放的问题:
下面的这种是根本没有可能得到释放的了:

flags = extract_string_tokens(str, "|", &n);

这是因为 flags根本不是返回的值

我们调用了 
pool_get_config 函数,pool_get_config函数中调用 extract_string_tokens ,
此后, 根本无从 保存 flags 指针。所以这段内存,在pgpool运行结束后,只能说是 “丢了"。

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

 

本文转自健哥的数据花园博客园博客,原文链接:http://www.cnblogs.com/gaojian/archive/2012/08/21/2649124.html,如需转载请自行联系原作者
相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
4月前
|
存储 监控 Java
内存泄漏及其解决方法
内存泄漏及其解决方法
64 0
|
Java 程序员 C++
troubleshoot之:使用JFR解决内存泄露
troubleshoot之:使用JFR解决内存泄露
troubleshoot之:使用JFR解决内存泄露
|
NoSQL Linux Redis
关于redis源码的内存分配,jemalloc,tcmalloc,libc
关于redis源码的内存分配,jemalloc,tcmalloc,libc
788 0
|
PHP
避免PHP-FPM内存泄漏导致内存耗尽
对于PHP-FPM多进程的模式,想要避免内存泄漏问题很简单,就是要让PHP-CGI在处理一定数量进程后退出即可。否则PHP程序或第三方模块(如Imagemagick扩展)导致的内存泄漏问题会导致内存耗尽或不足。
1177 0
|
关系型数据库 PostgreSQL 索引
|
关系型数据库 PostgreSQL 索引
|
索引 关系型数据库 PostgreSQL
|
关系型数据库 PostgreSQL 索引