From e89cdd504c3df5073f5876d011f7550d83924e79 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Fri, 15 Nov 2019 15:50:13 +0100 Subject: [PATCH] AK: Fix leak in WeakPtr(WeakPtr&&) and WeakPtr::operator=(WeakPtr&&) We were forgetting to adopt the WeakLink, causing a reference leak. This ended up costing us one allocation per exec(), with this stack: kmalloc_impl() Inode::set_vmo() InodeVMObject::create_with_inode() Process::do_exec() Process::exec() Process::sys$execve() This was a pain to track down, in the end I caught it by dumping out every live kmalloc pointer between runs and diffing the sets. Then it was just a matter of matching the pointer to a call stack and looking at what went wrong. :^) --- AK/WeakPtr.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/AK/WeakPtr.h b/AK/WeakPtr.h index 1b8297b356..290a12a0b7 100644 --- a/AK/WeakPtr.h +++ b/AK/WeakPtr.h @@ -18,14 +18,14 @@ public: template WeakPtr(WeakPtr&& other) - : m_link(reinterpret_cast*>(other.leak_link())) + : m_link(reinterpret_cast*>(other.take_link().ptr())) { } template WeakPtr& operator=(WeakPtr&& other) { - m_link = reinterpret_cast*>(other.leak_link()); + m_link = reinterpret_cast*>(other.take_link().ptr()); return *this; } @@ -46,7 +46,7 @@ public: bool is_null() const { return !m_link || !m_link->ptr(); } void clear() { m_link = nullptr; } - WeakLink* leak_link() { return m_link.leak_ref(); } + RefPtr> take_link() { return move(m_link); } bool operator==(const OwnPtr& other) const { return ptr() == other.ptr(); }