Bug 1384395 - Use nsAutoOwningThread for mfbt/WeakPtr.h thread assertions (r=froydnj)

MozReview-Commit-ID: DF4DiffL4Qq
This commit is contained in:
Bill McCloskey 2017-05-26 14:21:28 -07:00
parent bc07dbc87a
commit 7e43e5439d
3 changed files with 25 additions and 19 deletions

View file

@ -70,12 +70,20 @@
#include "mozilla/ArrayUtils.h" #include "mozilla/ArrayUtils.h"
#include "mozilla/Assertions.h" #include "mozilla/Assertions.h"
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
#include "mozilla/Maybe.h"
#include "mozilla/RefCounted.h" #include "mozilla/RefCounted.h"
#include "mozilla/RefPtr.h" #include "mozilla/RefPtr.h"
#include "mozilla/TypeTraits.h" #include "mozilla/TypeTraits.h"
#include <string.h> #include <string.h>
#if defined(MOZILLA_INTERNAL_API)
// For thread safety checking.
#include "nsISupportsImpl.h"
#endif
#if defined(MOZILLA_INTERNAL_API) && defined(MOZ_THREAD_SAFETY_OWNERSHIP_CHECKS_SUPPORTED)
// Weak referencing is not implemeted as thread safe. When a WeakPtr // Weak referencing is not implemeted as thread safe. When a WeakPtr
// is created or dereferenced on thread A but the real object is just // is created or dereferenced on thread A but the real object is just
// being Released() on thread B, there is a possibility of a race // being Released() on thread B, there is a possibility of a race
@ -89,31 +97,21 @@
// on a single thread. The following macros implement assertions for // on a single thread. The following macros implement assertions for
// checking these conditions. // checking these conditions.
// //
// We disable this on MinGW. MinGW has two threading models: win32 // We re-use XPCOM's nsAutoOwningThread checks when they are available. This has
// API based, which disables std::thread; and POSIX based which // the advantage that it works with cooperative thread pools.
// enables it but requires an emulation library (winpthreads).
// Rather than attempting to switch to pthread emulation at this point,
// we are disabling the std::thread based assertion checking.
//
// In the future, to enable it we could
// a. have libgcc/stdc++ support win32 threads natively
// b. switch to POSIX-based threading in MinGW with pthread emulation
// c. refactor it to not use std::thread
#if !defined(__MINGW32__) && (defined(DEBUG) || (defined(NIGHTLY_BUILD) && !defined(MOZ_PROFILING)))
#include <thread>
#define MOZ_WEAKPTR_DECLARE_THREAD_SAFETY_CHECK \ #define MOZ_WEAKPTR_DECLARE_THREAD_SAFETY_CHECK \
std::thread::id _owningThread; \ /* Will be none if mPtr = nullptr. */ \
bool _empty; // If it was initialized as a placeholder with mPtr = nullptr. Maybe<nsAutoOwningThread> _owningThread;
#define MOZ_WEAKPTR_INIT_THREAD_SAFETY_CHECK() \ #define MOZ_WEAKPTR_INIT_THREAD_SAFETY_CHECK() \
do { \ do { \
_owningThread = std::this_thread::get_id(); \ if (p) { \
_empty = !p; \ _owningThread.emplace(); \
} \
} while (false) } while (false)
#define MOZ_WEAKPTR_ASSERT_THREAD_SAFETY() \ #define MOZ_WEAKPTR_ASSERT_THREAD_SAFETY() \
do { \ do { \
if (!(_empty || _owningThread == std::this_thread::get_id())) { \ if (_owningThread.isSome() && !_owningThread.ref().IsCurrentThread()) { \
WeakPtrTraits<T>::AssertSafeToAccessFromNonOwningThread(); \ WeakPtrTraits<T>::AssertSafeToAccessFromNonOwningThread(); \
} \ } \
} while (false) } while (false)

View file

@ -38,9 +38,15 @@ nsAutoOwningThread::nsAutoOwningThread()
void void
nsAutoOwningThread::AssertCurrentThreadOwnsMe(const char* msg) const nsAutoOwningThread::AssertCurrentThreadOwnsMe(const char* msg) const
{ {
if (MOZ_UNLIKELY(mThread != GetCurrentVirtualThread())) { if (MOZ_UNLIKELY(!IsCurrentThread())) {
// `msg` is a string literal by construction. // `msg` is a string literal by construction.
MOZ_CRASH_UNSAFE_OOL(msg); MOZ_CRASH_UNSAFE_OOL(msg);
} }
} }
bool
nsAutoOwningThread::IsCurrentThread() const
{
return mThread == GetCurrentVirtualThread();
}
#endif #endif

View file

@ -69,6 +69,8 @@ public:
AssertCurrentThreadOwnsMe(aMsg); AssertCurrentThreadOwnsMe(aMsg);
} }
bool IsCurrentThread() const;
private: private:
void AssertCurrentThreadOwnsMe(const char* aMsg) const; void AssertCurrentThreadOwnsMe(const char* aMsg) const;