mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 21:22:46 +00:00 
			
		
		
		
	 e89cdd504c
			
		
	
	
		e89cdd504c
		
	
	
	
	
		
			
			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. :^)
		
	
			
		
			
				
	
	
		
			78 lines
		
	
	
	
		
			1.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			78 lines
		
	
	
	
		
			1.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #pragma once
 | |
| 
 | |
| #include <AK/LogStream.h>
 | |
| #include <AK/Weakable.h>
 | |
| 
 | |
| namespace AK {
 | |
| 
 | |
| template<typename T>
 | |
| class OwnPtr;
 | |
| 
 | |
| template<typename T>
 | |
| class WeakPtr {
 | |
|     friend class Weakable<T>;
 | |
| 
 | |
| public:
 | |
|     WeakPtr() {}
 | |
|     WeakPtr(std::nullptr_t) {}
 | |
| 
 | |
|     template<typename U>
 | |
|     WeakPtr(WeakPtr<U>&& other)
 | |
|         : 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.take_link().ptr());
 | |
|         return *this;
 | |
|     }
 | |
| 
 | |
|     operator bool() const { return ptr(); }
 | |
| 
 | |
|     T* ptr() { return m_link ? m_link->ptr() : nullptr; }
 | |
|     const T* ptr() const { return m_link ? m_link->ptr() : nullptr; }
 | |
| 
 | |
|     T* operator->() { return ptr(); }
 | |
|     const T* operator->() const { return ptr(); }
 | |
| 
 | |
|     T& operator*() { return *ptr(); }
 | |
|     const T& operator*() const { return *ptr(); }
 | |
| 
 | |
|     operator const T*() const { return ptr(); }
 | |
|     operator T*() { return ptr(); }
 | |
| 
 | |
|     bool is_null() const { return !m_link || !m_link->ptr(); }
 | |
|     void clear() { m_link = nullptr; }
 | |
| 
 | |
|     RefPtr<WeakLink<T>> take_link() { return move(m_link); }
 | |
| 
 | |
|     bool operator==(const OwnPtr<T>& other) const { return ptr() == other.ptr(); }
 | |
| 
 | |
| private:
 | |
|     WeakPtr(RefPtr<WeakLink<T>> link)
 | |
|         : m_link(move(link))
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     RefPtr<WeakLink<T>> m_link;
 | |
| };
 | |
| 
 | |
| template<typename T>
 | |
| inline WeakPtr<T> Weakable<T>::make_weak_ptr()
 | |
| {
 | |
|     if (!m_link)
 | |
|         m_link = adopt(*new WeakLink<T>(static_cast<T&>(*this)));
 | |
|     return WeakPtr<T>(m_link);
 | |
| }
 | |
| 
 | |
| template<typename T>
 | |
| inline const LogStream& operator<<(const LogStream& stream, const WeakPtr<T>& value)
 | |
| {
 | |
|     return stream << value.ptr();
 | |
| }
 | |
| 
 | |
| }
 | |
| 
 | |
| using AK::WeakPtr;
 |