mirror of
https://github.com/postgres/postgres.git
synced 2025-10-10 00:03:27 -04:00
Suppress complaints about leaks in TS dictionary loading.
Like the situation with function cache loading, text search dictionary loading functions tend to leak some cruft into the dictionary's long-lived cache context. To judge by the examples in the core regression tests, not very many bytes are at stake. Moreover, I don't see a way to prevent such leaks without changing the API for TS template initialization functions: right now they do not have to worry about making sure that their results are long-lived. Hence, I think we should install a suppression rule rather than trying to fix this completely. However, I did grab some low-hanging fruit: several places were leaking the result of get_tsearch_config_filename. This seems worth doing mostly because they are inconsistent with other dictionaries that were freeing it already. Author: Tom Lane <tgl@sss.pgh.pa.us> Reviewed-by: Andres Freund <andres@anarazel.de> Discussion: https://postgr.es/m/285483.1746756246@sss.pgh.pa.us
This commit is contained in:
parent
2c7b4ad24d
commit
7f6ededa76
@ -47,24 +47,30 @@ dispell_init(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
if (strcmp(defel->defname, "dictfile") == 0)
|
if (strcmp(defel->defname, "dictfile") == 0)
|
||||||
{
|
{
|
||||||
|
char *filename;
|
||||||
|
|
||||||
if (dictloaded)
|
if (dictloaded)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||||
errmsg("multiple DictFile parameters")));
|
errmsg("multiple DictFile parameters")));
|
||||||
NIImportDictionary(&(d->obj),
|
filename = get_tsearch_config_filename(defGetString(defel),
|
||||||
get_tsearch_config_filename(defGetString(defel),
|
"dict");
|
||||||
"dict"));
|
NIImportDictionary(&(d->obj), filename);
|
||||||
|
pfree(filename);
|
||||||
dictloaded = true;
|
dictloaded = true;
|
||||||
}
|
}
|
||||||
else if (strcmp(defel->defname, "afffile") == 0)
|
else if (strcmp(defel->defname, "afffile") == 0)
|
||||||
{
|
{
|
||||||
|
char *filename;
|
||||||
|
|
||||||
if (affloaded)
|
if (affloaded)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||||
errmsg("multiple AffFile parameters")));
|
errmsg("multiple AffFile parameters")));
|
||||||
NIImportAffixes(&(d->obj),
|
filename = get_tsearch_config_filename(defGetString(defel),
|
||||||
get_tsearch_config_filename(defGetString(defel),
|
"affix");
|
||||||
"affix"));
|
NIImportAffixes(&(d->obj), filename);
|
||||||
|
pfree(filename);
|
||||||
affloaded = true;
|
affloaded = true;
|
||||||
}
|
}
|
||||||
else if (strcmp(defel->defname, "stopwords") == 0)
|
else if (strcmp(defel->defname, "stopwords") == 0)
|
||||||
|
@ -199,6 +199,7 @@ skipline:
|
|||||||
}
|
}
|
||||||
|
|
||||||
tsearch_readline_end(&trst);
|
tsearch_readline_end(&trst);
|
||||||
|
pfree(filename);
|
||||||
|
|
||||||
d->len = cur;
|
d->len = cur;
|
||||||
qsort(d->syn, d->len, sizeof(Syn), compareSyn);
|
qsort(d->syn, d->len, sizeof(Syn), compareSyn);
|
||||||
|
@ -167,17 +167,17 @@ addWrd(DictThesaurus *d, char *b, char *e, uint32 idsubst, uint16 nwrd, uint16 p
|
|||||||
static void
|
static void
|
||||||
thesaurusRead(const char *filename, DictThesaurus *d)
|
thesaurusRead(const char *filename, DictThesaurus *d)
|
||||||
{
|
{
|
||||||
|
char *real_filename = get_tsearch_config_filename(filename, "ths");
|
||||||
tsearch_readline_state trst;
|
tsearch_readline_state trst;
|
||||||
uint32 idsubst = 0;
|
uint32 idsubst = 0;
|
||||||
bool useasis = false;
|
bool useasis = false;
|
||||||
char *line;
|
char *line;
|
||||||
|
|
||||||
filename = get_tsearch_config_filename(filename, "ths");
|
if (!tsearch_readline_begin(&trst, real_filename))
|
||||||
if (!tsearch_readline_begin(&trst, filename))
|
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_CONFIG_FILE_ERROR),
|
(errcode(ERRCODE_CONFIG_FILE_ERROR),
|
||||||
errmsg("could not open thesaurus file \"%s\": %m",
|
errmsg("could not open thesaurus file \"%s\": %m",
|
||||||
filename)));
|
real_filename)));
|
||||||
|
|
||||||
while ((line = tsearch_readline(&trst)) != NULL)
|
while ((line = tsearch_readline(&trst)) != NULL)
|
||||||
{
|
{
|
||||||
@ -297,6 +297,7 @@ thesaurusRead(const char *filename, DictThesaurus *d)
|
|||||||
d->nsubst = idsubst;
|
d->nsubst = idsubst;
|
||||||
|
|
||||||
tsearch_readline_end(&trst);
|
tsearch_readline_end(&trst);
|
||||||
|
pfree(real_filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
static TheLexeme *
|
static TheLexeme *
|
||||||
|
4
src/backend/utils/cache/ts_cache.c
vendored
4
src/backend/utils/cache/ts_cache.c
vendored
@ -321,7 +321,9 @@ lookup_ts_dictionary_cache(Oid dictId)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Init method runs in dictionary's private memory context, and we
|
* Init method runs in dictionary's private memory context, and we
|
||||||
* make sure the options are stored there too
|
* make sure the options are stored there too. This typically
|
||||||
|
* results in a small amount of memory leakage, but it's not worth
|
||||||
|
* complicating the API for tmplinit functions to avoid it.
|
||||||
*/
|
*/
|
||||||
oldcontext = MemoryContextSwitchTo(entry->dictCtx);
|
oldcontext = MemoryContextSwitchTo(entry->dictCtx);
|
||||||
|
|
||||||
|
@ -215,3 +215,15 @@
|
|||||||
...
|
...
|
||||||
fun:cached_function_compile
|
fun:cached_function_compile
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Suppress complaints about stuff leaked during TS dictionary loading.
|
||||||
|
# Not very much is typically lost there, and preventing it would
|
||||||
|
# require a risky API change for TS tmplinit functions.
|
||||||
|
{
|
||||||
|
hide_ts_dictionary_leaks
|
||||||
|
Memcheck:Leak
|
||||||
|
match-leak-kinds: definite,possible,indirect
|
||||||
|
|
||||||
|
...
|
||||||
|
fun:lookup_ts_dictionary_cache
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user