Changeset 250762 in webkit


Ignore:
Timestamp:
Oct 4, 2019 6:59:35 PM (5 years ago)
Author:
rniwa@webkit.org
Message:

Make a ThreadSafeRefCounted object safe to ref & deref inside its destructor
https://bugs.webkit.org/show_bug.cgi?id=201576

Reviewed by Geoffrey Garen.

This patch leaves m_refCount 1 inside the last deref call to ThreadSafeRefCounted
such that ref'ing and deref'ing it again inside its destructor would never try
to double delete the object.

Also added m_deletionHasBegun like RefCounted.

  • wtf/ThreadSafeRefCounted.h:

(WTF::ThreadSafeRefCountedBase::ref const):
(WTF::ThreadSafeRefCountedBase::hasOneRef const):
(WTF::ThreadSafeRefCountedBase::derefBase const):

Location:
trunk/Source/WTF
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WTF/ChangeLog

    r250747 r250762  
     12019-10-04  Ryosuke Niwa  <rniwa@webkit.org>
     2
     3        Make a ThreadSafeRefCounted object safe to ref & deref inside its destructor
     4        https://bugs.webkit.org/show_bug.cgi?id=201576
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        This patch leaves m_refCount 1 inside the last deref call to ThreadSafeRefCounted
     9        such that ref'ing and deref'ing it again inside its destructor would never try
     10        to double delete the object.
     11
     12        Also added m_deletionHasBegun like RefCounted.
     13
     14        * wtf/ThreadSafeRefCounted.h:
     15        (WTF::ThreadSafeRefCountedBase::ref const):
     16        (WTF::ThreadSafeRefCountedBase::hasOneRef const):
     17        (WTF::ThreadSafeRefCountedBase::derefBase const):
     18
    1192019-10-04  Heiko Becker  <heirecka@exherbo.org>
    220
  • trunk/Source/WTF/wtf/ThreadSafeRefCounted.h

    r247078 r250762  
    3333namespace WTF {
    3434
     35#if defined(NDEBUG) && !ENABLE(SECURITY_ASSERTIONS)
     36#define CHECK_THREAD_SAFE_REF_COUNTED_LIFECYCLE 0
     37#else
     38#define CHECK_THREAD_SAFE_REF_COUNTED_LIFECYCLE 1
     39#endif
     40
    3541class ThreadSafeRefCountedBase {
    3642    WTF_MAKE_NONCOPYABLE(ThreadSafeRefCountedBase);
     
    3945    ThreadSafeRefCountedBase() = default;
    4046
     47#if CHECK_THREAD_SAFE_REF_COUNTED_LIFECYCLE
     48    ~ThreadSafeRefCountedBase()
     49    {
     50        // When this ThreadSafeRefCounted object is a part of another object, derefBase() is never called on this object.
     51        m_deletionHasBegun = true;
     52    }
     53#endif
     54
    4155    void ref() const
    4256    {
     57#if CHECK_THREAD_SAFE_REF_COUNTED_LIFECYCLE
     58        ASSERT_WITH_SECURITY_IMPLICATION(!m_deletionHasBegun);
     59#endif
    4360        ++m_refCount;
    4461    }
     
    4663    bool hasOneRef() const
    4764    {
     65#if CHECK_THREAD_SAFE_REF_COUNTED_LIFECYCLE
     66        ASSERT(!m_deletionHasBegun);
     67#endif
    4868        return refCount() == 1;
    4969    }
     
    5878    bool derefBase() const
    5979    {
    60         return !--m_refCount;
     80        ASSERT(m_refCount);
     81
     82#if CHECK_THREAD_SAFE_REF_COUNTED_LIFECYCLE
     83        ASSERT_WITH_SECURITY_IMPLICATION(!m_deletionHasBegun);
     84#endif
     85
     86        if (UNLIKELY(!--m_refCount)) {
     87            // Setting m_refCount to 1 here prevents double delete within the destructor but not from another thread
     88            // since such a thread could have ref'ed this object long after it had been deleted. See webkit.org/b/201576.
     89            m_refCount = 1;
     90#if CHECK_THREAD_SAFE_REF_COUNTED_LIFECYCLE
     91            m_deletionHasBegun = true;
     92#endif
     93            return true;
     94        }
     95
     96        return false;
    6197    }
    6298
    6399private:
    64100    mutable std::atomic<unsigned> m_refCount { 1 };
     101
     102#if CHECK_THREAD_SAFE_REF_COUNTED_LIFECYCLE
     103    mutable std::atomic<bool> m_deletionHasBegun { false };
     104#endif
    65105};
    66106
Note: See TracChangeset for help on using the changeset viewer.