summaryrefslogtreecommitdiff
path: root/Kernel
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2021-09-07 20:31:30 +0200
committerAndreas Kling <kling@serenityos.org>2021-09-07 22:16:25 +0200
commit5159f641174c421ef9250abdc7026a42d52c54b8 (patch)
treebfea0e1660c29274d5367fd86ce3d139ec42493e /Kernel
parent049d846eb9964c8ea305e801d46bb61791809c6e (diff)
downloadserenity-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.h18
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;
}
};