MDEV-36345: Memleak on shutdown in acl_load_mutex test#4895
MDEV-36345: Memleak on shutdown in acl_load_mutex test#4895kjarir wants to merge 1 commit intoMariaDB:10.11from
Conversation
In plugin_add(), init_alloc_root() was called unconditionally after plugin_insert_or_reuse(), even when my_hash_insert() failed and the plugin state was set to PLUGIN_IS_FREED. This caused a memory leak because the newly initialized mem_root was never freed — plugin_del() only frees mem_root for plugins that go through the normal deletion path, not ones immediately marked as PLUGIN_IS_FREED due to hash insertion failure. Fix: Guard init_alloc_root() with else so it is only called when my_hash_insert() succeeds.
gkodinov
left a comment
There was a problem hiding this comment.
Thank you for your contribution! This is a preliminary review.
This is an interesting analysis! I have one question:
How come my_hash_insert() can fail at that point?
The code does the following:
- takes a lock guarding the plugin hash
- looks for the plugin into plugin hash, fails if found
- constructs a new plugin hash entry
- tries to insert it while holding the lock
Looking at my_hash_insert() Inserting that new hash entry can fails because:
- the hash has an entry with the same name
- there's no more memory
I fail to understand how my_hash_insert() can fail due to a duplicate entry: it's just been checked under the same lock hold.
Yes, it can fail due to lack of memory. But then you'd have bigger issues.
And now the formal reason: I've tried running the test mentioned under asan/msan, but I do not get any issues. Neither does buildbot. Can you please think of a test case that would expose this problem?
Frankly, I can't at this point. Hence my question above.
|
Thank you for the detailed review @gkodinov These are valid points. My ASAN trace was on macOS (Apple Clang, ARM64) which may behave differently from Linux. I'm investigating further to find a proper reproducer on Linux and will update the PR once I have a clearer picture. |
Problem
In plugin_add(), init_alloc_root() was called unconditionally after plugin_insert_or_reuse(), even when my_hash_insert() failed and the plugin state was set to PLUGIN_IS_FREED.
This mem_root was never freed because plugin_del() only runs free_root() on plugins that go through the normal deletion path. Plugins immediately marked PLUGIN_IS_FREED skip this path entirely, causing the leak detected by LeakSanitizer during the roles.acl_load_mutex test.
Fix
Guard init_alloc_root() inside the else branch of my_hash_insert() so it is only called when plugin registration succeeds.
Testing
Verified with ASAN+UBSAN build (clang, Debug):