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. :^)
This commit is contained in:
Andreas Kling 2019-11-15 15:50:13 +01:00
parent 7ef9c703d2
commit e89cdd504c
Notes: sideshowbarker 2024-07-19 11:13:08 +09:00

View file

@ -18,14 +18,14 @@ public:
template<typename U>
WeakPtr(WeakPtr<U>&& other)
: m_link(reinterpret_cast<WeakLink<T>*>(other.leak_link()))
: m_link(reinterpret_cast<WeakLink<T>*>(other.take_link().ptr()))
{
}
template<typename U>
WeakPtr& operator=(WeakPtr<U>&& other)
{
m_link = reinterpret_cast<WeakLink<T>*>(other.leak_link());
m_link = reinterpret_cast<WeakLink<T>*>(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<T>* leak_link() { return m_link.leak_ref(); }
RefPtr<WeakLink<T>> take_link() { return move(m_link); }
bool operator==(const OwnPtr<T>& other) const { return ptr() == other.ptr(); }