diff options
author | Andreas Kling <kling@serenityos.org> | 2021-09-07 20:31:30 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-09-07 22:16:25 +0200 |
commit | 5159f641174c421ef9250abdc7026a42d52c54b8 (patch) | |
tree | bfea0e1660c29274d5367fd86ce3d139ec42493e /Kernel | |
parent | 049d846eb9964c8ea305e801d46bb61791809c6e (diff) | |
download | serenity-5159f641174c421ef9250abdc7026a42d52c54b8.zip |
Kernel: Stop leaking TmpFS inodes
TmpFS inodes rely on the call to Inode::one_ref_left() to unregister
themselves from the inode cache in TmpFS.
When moving various kernel classes to ListedRefCounted for safe unref()
while participating on lists, I forgot to make ListedRefCounted check
for (and call) one_ref_left() & will_be_destroyed() on the CRTP class.
Diffstat (limited to 'Kernel')
-rw-r--r-- | Kernel/Library/ListedRefCounted.h | 18 |
1 files changed, 11 insertions, 7 deletions
diff --git a/Kernel/Library/ListedRefCounted.h b/Kernel/Library/ListedRefCounted.h index e9a98e8731..d0cabd75ba 100644 --- a/Kernel/Library/ListedRefCounted.h +++ b/Kernel/Library/ListedRefCounted.h @@ -20,15 +20,19 @@ class ListedRefCounted : public RefCountedBase { public: bool unref() const { - bool did_hit_zero = T::all_instances().with([&](auto& list) { - if (deref_base()) - return false; - list.remove(const_cast<T&>(static_cast<T const&>(*this))); - return true; + auto new_ref_count = T::all_instances().with([&](auto& list) { + auto new_ref_count = deref_base(); + if (new_ref_count == 0) + list.remove(const_cast<T&>(static_cast<T const&>(*this))); + return new_ref_count; }); - if (did_hit_zero) + if (new_ref_count == 0) { + call_will_be_destroyed_if_present(static_cast<const T*>(this)); delete const_cast<T*>(static_cast<T const*>(this)); - return did_hit_zero; + } else if (new_ref_count == 1) { + call_one_ref_left_if_present(static_cast<T const*>(this)); + } + return new_ref_count == 0; } }; |