pg-224: Fix memory leak on extract_query_comments.
There were two objects leaking memory in this function, the comments variable of type char * allocated using palloc0, and the regular expression object preg. If the regcomp function failed, the function was returning without releasing the comments variable allocated previously. If the regexec function failed, the function was returning without releasing the preg object and the comments variable. This commit does two changes, first it turns the comments in extract_query_comments an argument to the function, in pgss_store we declare the comments variable in the stack, so it will clean up after itself. The second change was to move the regular expression object to global scope, this way we compile the object only once, during module initialization. With these two changes we fix the memory leak and avoid allocating/releasing memory for every call to this function.pull/99/head
parent
3d3ece2f99
commit
b5aa300e82
|
@ -56,6 +56,8 @@ static int plan_nested_level = 0;
|
|||
/* The array to store outer layer query id*/
|
||||
uint64 *nested_queryids;
|
||||
|
||||
/* Regex object used to extract query comments. */
|
||||
static regex_t preg_query_comments;
|
||||
static char relations[REL_LST][REL_LEN];
|
||||
static int num_relations; /* Number of relation in the query */
|
||||
static bool system_init = false;
|
||||
|
@ -67,7 +69,7 @@ static char *pgss_explain(QueryDesc *queryDesc);
|
|||
static struct pg_hook_stats_t *pg_hook_stats;
|
||||
#endif
|
||||
|
||||
static char *extract_query_comments(const char *query);
|
||||
static void extract_query_comments(const char *query, char *comments, size_t max_len);
|
||||
static int get_histogram_bucket(double q_time);
|
||||
static bool IsSystemInitialized(void);
|
||||
static void dump_queries_buffer(int bucket_id, unsigned char *buf, int buf_len);
|
||||
|
@ -219,7 +221,8 @@ static uint64 djb2_hash(unsigned char *str, size_t len);
|
|||
void
|
||||
_PG_init(void)
|
||||
{
|
||||
int i;
|
||||
int i, rc;
|
||||
|
||||
elog(DEBUG2, "pg_stat_monitor: %s()", __FUNCTION__);
|
||||
/*
|
||||
* In order to create our shared memory area, we have to be loaded via
|
||||
|
@ -252,6 +255,15 @@ _PG_init(void)
|
|||
|
||||
EmitWarningsOnPlaceholders("pg_stat_monitor");
|
||||
|
||||
/*
|
||||
* Compile regular expression for extracting out query comments only once.
|
||||
*/
|
||||
rc = regcomp(&preg_query_comments, "/\\*.*\\*/", 0);
|
||||
if (rc != 0)
|
||||
{
|
||||
elog(ERROR, "pg_stat_monitor: query comments regcomp() failed, return code=(%d)\n", rc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Request additional shared resources. (These are no-ops if we're not in
|
||||
* the postmaster process.) We'll allocate or attach to the shared
|
||||
|
@ -307,6 +319,7 @@ _PG_fini(void)
|
|||
ProcessUtility_hook = prev_ProcessUtility;
|
||||
|
||||
free(nested_queryids);
|
||||
regfree(&preg_query_comments);
|
||||
|
||||
hash_entry_reset();
|
||||
}
|
||||
|
@ -1483,7 +1496,7 @@ pgss_store(uint64 queryid,
|
|||
uint64 ip = pg_get_client_addr();
|
||||
uint64 planid = plan_info ? plan_info->planid: 0;
|
||||
uint64 appid = djb2_hash((unsigned char *)application_name, application_name_len);
|
||||
char *comments;
|
||||
char comments[512] = "";
|
||||
/* Monitoring is disabled */
|
||||
if (!PGSM_ENABLED)
|
||||
return;
|
||||
|
@ -1494,7 +1507,7 @@ pgss_store(uint64 queryid,
|
|||
else
|
||||
userid = GetUserId();
|
||||
|
||||
comments = extract_query_comments(query);
|
||||
extract_query_comments(query, comments, sizeof(comments));
|
||||
|
||||
/* Safety check... */
|
||||
if (!IsSystemInitialized() || !pgss_qbuf[pgss->current_wbucket])
|
||||
|
@ -3407,29 +3420,20 @@ get_histogram_timings(PG_FUNCTION_ARGS)
|
|||
return CStringGetTextDatum(text_str);
|
||||
}
|
||||
|
||||
char *
|
||||
extract_query_comments(const char *query)
|
||||
static void
|
||||
extract_query_comments(const char *query, char *comments, size_t max_len)
|
||||
{
|
||||
regex_t preg;
|
||||
char *pattern = "/\\*.*\\*/";
|
||||
int rc;
|
||||
size_t nmatch = 1;
|
||||
regmatch_t pmatch;
|
||||
char *comments = palloc0(512);
|
||||
|
||||
rc = regcomp(&preg, pattern, 0);
|
||||
if (rc != 0)
|
||||
{
|
||||
printf("regcomp() failed, returning nonzero (%d)\n", rc);
|
||||
return "";
|
||||
}
|
||||
rc = regexec(&preg, query, nmatch, &pmatch, 0);
|
||||
if (rc != 0)
|
||||
return "";
|
||||
sprintf(comments, "%.*s", pmatch.rm_eo - pmatch.rm_so -4, &query[pmatch.rm_so + 2]);
|
||||
regfree(&preg);
|
||||
return comments;
|
||||
rc = regexec(&preg_query_comments, query, nmatch, &pmatch, 0);
|
||||
if (rc != 0)
|
||||
return;
|
||||
|
||||
snprintf(comments, max_len, "%.*s", pmatch.rm_eo - pmatch.rm_so -4, &query[pmatch.rm_so + 2]);
|
||||
}
|
||||
|
||||
#if PG_VERSION_NUM < 140000
|
||||
static uint64
|
||||
get_query_id(JumbleState *jstate, Query *query)
|
||||
|
|
Loading…
Reference in New Issue