Getting better results from valgrind leak tracking
Tom Lane <tgl@sss.pgh.pa.us>
From: Tom Lane <tgl@sss.pgh.pa.us>
To: Andres Freund <andres@anarazel.de>
Cc: pgsql-hackers@lists.postgresql.org
Date: 2021-03-16T23:36:10Z
Lists: pgsql-hackers
Attachments
- valgrind-leak-hacks.patch (text/x-diff) patch
[ starting a new thread for this ] Andres Freund <andres@anarazel.de> writes: > I wonder if it'd be worth starting to explicitly annotate all the places > that do allocations and are fine with leaking them. E.g. by introducing > malloc_permanently() or such. Right now it's hard to use valgrind et al > to detect leaks because of all the false positives due to such "ok to > leak" allocations. Out of curiosity I poked at this for a little while. It doesn't appear to me that we leak much at all, at least not if you are willing to take "still reachable" blocks as not-leaked. Most of the problem is more subtle than that. I found just a couple of things that really seem like leaks of permanent data structures to valgrind: * Where ps_status.c copies the original "environ" array (on PS_USE_CLOBBER_ARGV platforms), valgrind thinks that's all leaked, implying that it doesn't count the "environ" global as a valid reference to leakable data. I was able to shut that up by also saving the pointer into an otherwise-unused static variable. (This is sort of a poor man's implementation of your "malloc_permanently" idea; but I doubt it's worth working harder, given the small number of use-cases.) * The postmaster's sock_paths and lock_files lists appear to be leaked, but we're doing that to ourselves by throwing away the pointers to them without physically freeing the lists. We can just not do that. What I found out is that we have a lot of issues that seem to devolve to valgrind not being sure that a block is referenced. I identified two main causes of that: (1) We have a pointer, but it doesn't actually point right at the start of the block. A primary culprit here is lists of thingies that use the slist and dlist infrastructure. As an experiment, I moved the dlist_node fields of some popular structs to the beginning, and verified that that silences associated complaints. I'm not sure that we want to insist on put-the-link-first as policy (although if we did, it could provide some notational savings perhaps). However, unless someone knows of a way to teach valgrind about this situation, there may be no other way to silence those leakage complaints. A secondary culprit is people randomly applying CACHELINEALIGN or the like to a palloc'd address, so that the address we have isn't pointing right at the block start. (2) The only pointer to the start of a block is actually somewhere within the block. This is common in dynahash tables, where we allocate a slab of entries in a single palloc and then thread them together. Each entry should have exactly one referencing pointer, but that pointer is more likely to be elsewhere within the same palloc block than in the external hash bucket array. AFAICT, all cases except where the slab's first entry is pointed to by a hash bucket pointer confuse valgrind to some extent. I was able to hack around this by preventing dynahash from allocating more than one hash entry per palloc, but I wonder if there's a better way. Attached is a very crude hack, not meant for commit, that hacks things up enough to greatly reduce the number of complaints with "--leak-check=full". One thing I've failed to silence so far is a bunch of entries like ==00:00:03:56.088 3467702== 1,861 bytes in 67 blocks are definitely lost in loss record 1,290 of 1,418 ==00:00:03:56.088 3467702== at 0x950650: MemoryContextAlloc (mcxt.c:827) ==00:00:03:56.088 3467702== by 0x951710: MemoryContextStrdup (mcxt.c:1179) ==00:00:03:56.088 3467702== by 0x91C86E: RelationInitIndexAccessInfo (relcache.c:1444) ==00:00:03:56.088 3467702== by 0x91DA9C: RelationBuildDesc (relcache.c:1200) which is complaining about the memory context identifiers for system indexes' rd_indexcxt contexts. Those are surely not being leaked in any real sense. I suspect that this has something to do with valgrind not counting the context->ident fields as live pointers, but I don't have enough valgrind-fu to fix that. Anyway, the bottom line is that I do not think that we have all that many uses of the pattern you postulated originally. It's more that we've designed some valgrind-unfriendly data structures. We need to improve that situation to make much progress here. regards, tom lane
Commits
-
Improve our support for Valgrind's leak tracking.
- bb049a79d344 19 (unreleased) landed
-
Increment xactCompletionCount during subtransaction abort.
- 90c885cdab8b 14.0 landed
-
Adjust design of per-worker parallel seqscan data struct
- af527705edc3 14.0 landed
-
Don't leak compiled regex(es) when an ispell cache entry is dropped.
- d303849b059c 14.0 landed
- eba939551afe 13.3 landed
- 92bc14a1027d 12.7 landed
- 0b618ddf8bb2 10.17 landed
- 09e961929614 9.6.22 landed
- 099d2914f30b 11.12 landed
-
Don't leak malloc'd error string in libpqrcv_check_conninfo().
- 9bacdf9f536a 14.0 landed
- ba986b7bc5cf 10.17 landed
- 4eca51d44641 12.7 landed
- 20f11ca0dbc2 11.12 landed
- 12354839e874 13.3 landed
-
Don't leak malloc'd strings when a GUC setting is rejected.
- 377b7a83007d 14.0 landed
- fc552f8680a7 12.7 landed
- 7e25217701cc 9.6.22 landed
- 642b0b69b063 13.3 landed
- 5058e95a6ef9 10.17 landed
- 26a3ae06d85c 11.12 landed
-
Don't leak rd_statlist when a relcache entry is dropped.
- 28644fac1073 14.0 landed
- fbcc9fe33c43 12.7 landed
- 967b693eaef1 11.12 landed
- 536836970144 13.3 landed
- 2bed650c4841 10.17 landed
-
Don't run RelationInitTableAccessMethod in a long-lived context.
- 415ffdc2205e 14.0 landed
- ea3989f3496c 13.3 landed
- 1452a0bb87c7 12.7 landed