Backed out changeset 4887ddabba31 (bug 939231) for mochitest hangs.

CLOSED TREE
This commit is contained in:
Ryan VanderMeulen 2013-11-21 09:39:38 -05:00
parent 1c0b7690cc
commit 6a90626b1d
5 changed files with 49 additions and 78 deletions

View File

@ -39,7 +39,7 @@ BlockingResourceBase::DeadlockDetectorEntry::Print(
bool aPrintFirstSeenCx) const bool aPrintFirstSeenCx) const
{ {
CallStack lastAcquisition = mAcquisitionContext; // RACY, but benign CallStack lastAcquisition = mAcquisitionContext; // RACY, but benign
bool maybeCurrentlyAcquired = !lastAcquisition.IsEmpty(); bool maybeCurrentlyAcquired = (CallStack::kNone != lastAcquisition);
CallStack printAcquisition = CallStack printAcquisition =
(aPrintFirstSeenCx || !maybeCurrentlyAcquired) ? (aPrintFirstSeenCx || !maybeCurrentlyAcquired) ?
aFirstSeen.mCallContext : lastAcquisition; aFirstSeen.mCallContext : lastAcquisition;
@ -134,7 +134,7 @@ BlockingResourceBase::Acquire(const CallStack& aCallContext)
"FIXME bug 456272: annots. to allow Acquire()ing condvars"); "FIXME bug 456272: annots. to allow Acquire()ing condvars");
return; return;
} }
NS_ASSERTION(mDDEntry->mAcquisitionContext.IsEmpty(), NS_ASSERTION(mDDEntry->mAcquisitionContext == CallStack::kNone,
"reacquiring already acquired resource"); "reacquiring already acquired resource");
ResourceChainAppend(ResourceChainFront()); ResourceChainAppend(ResourceChainFront());
@ -152,7 +152,8 @@ BlockingResourceBase::Release()
} }
BlockingResourceBase* chainFront = ResourceChainFront(); BlockingResourceBase* chainFront = ResourceChainFront();
NS_ASSERTION(chainFront && !mDDEntry->mAcquisitionContext.IsEmpty(), NS_ASSERTION(chainFront
&& CallStack::kNone != mDDEntry->mAcquisitionContext,
"Release()ing something that hasn't been Acquire()ed"); "Release()ing something that hasn't been Acquire()ed");
if (chainFront == this) { if (chainFront == this) {
@ -177,7 +178,7 @@ BlockingResourceBase::Release()
curr->mChainPrev = prev->mChainPrev; curr->mChainPrev = prev->mChainPrev;
} }
mDDEntry->mAcquisitionContext = CallStack::NullCallStack(); mDDEntry->mAcquisitionContext = CallStack::kNone;
} }
@ -300,7 +301,7 @@ ReentrantMonitor::Wait(PRIntervalTime interval)
CallStack savedAcquisitionContext = GetAcquisitionContext(); CallStack savedAcquisitionContext = GetAcquisitionContext();
BlockingResourceBase* savedChainPrev = mChainPrev; BlockingResourceBase* savedChainPrev = mChainPrev;
mEntryCount = 0; mEntryCount = 0;
SetAcquisitionContext(CallStack::NullCallStack()); SetAcquisitionContext(CallStack::kNone);
mChainPrev = 0; mChainPrev = 0;
// give up the monitor until we're back from Wait() // give up the monitor until we're back from Wait()
@ -327,7 +328,7 @@ CondVar::Wait(PRIntervalTime interval)
// save mutex state and reset to empty // save mutex state and reset to empty
CallStack savedAcquisitionContext = mLock->GetAcquisitionContext(); CallStack savedAcquisitionContext = mLock->GetAcquisitionContext();
BlockingResourceBase* savedChainPrev = mLock->mChainPrev; BlockingResourceBase* savedChainPrev = mLock->mChainPrev;
mLock->SetAcquisitionContext(CallStack::NullCallStack()); mLock->SetAcquisitionContext(CallStack::kNone);
mLock->mChainPrev = 0; mLock->mChainPrev = 0;
// give up mutex until we're back from Wait() // give up mutex until we're back from Wait()

View File

@ -74,7 +74,7 @@ private:
BlockingResourceType aType) : BlockingResourceType aType) :
mName(aName), mName(aName),
mType(aType), mType(aType),
mAcquisitionContext(CallStack::NullCallStack()) mAcquisitionContext(CallStack::kNone)
{ {
NS_ABORT_IF_FALSE(mName, "Name must be nonnull"); NS_ABORT_IF_FALSE(mName, "Name must be nonnull");
} }
@ -117,7 +117,7 @@ private:
/** /**
* mAcquisitionContext * mAcquisitionContext
* The calling context from which this resource was acquired, or * The calling context from which this resource was acquired, or
* |CallStack::NullCallStack()| if it is currently free (or freed). * |CallStack::kNone| if it is currently free (or freed).
*/ */
CallStack mAcquisitionContext; CallStack mAcquisitionContext;
}; };
@ -239,7 +239,7 @@ protected:
/** /**
* GetAcquisitionContext * GetAcquisitionContext
* Return the calling context from which this resource was acquired, * Return the calling context from which this resource was acquired,
* or CallStack::NullCallStack() if it's currently free. * or CallStack::kNone if it's currently free.
* *
* *NOT* thread safe. Requires ownership of underlying resource. * *NOT* thread safe. Requires ownership of underlying resource.
*/ */

View File

@ -5,46 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "DeadlockDetector.h" #include "DeadlockDetector.h"
#include "nsStackWalk.h"
#include "mozilla/Util.h"
namespace mozilla { namespace mozilla {
const CallStack CallStack::kNone((CallStack::callstack_id) -1);
static void
StackCallback(void* pc, void* sp, void* closure)
{
nsTArray<void*>* stack = static_cast<nsTArray<void*>*>(closure);
stack->AppendElement(pc);
}
nsTArray<void*>
CallStack::GetBacktrace()
{
nsTArray<void*> callstack;
callstack.SetCapacity(32); // Hopefully 32 frames is a good average
NS_StackWalk(StackCallback, 2, 0, &callstack, 0, nullptr);
return mozilla::Move(callstack);
}
void
CallStack::Print(FILE* f) const
{
if (mCallStack.IsEmpty()) {
fputs(" [stack trace unavailable]\n", f);
} else {
nsCodeAddressDetails addr;
for (uint32_t i = 0; i < mCallStack.Length(); ++i) {
nsresult rv = NS_DescribeCodeAddress(mCallStack[i], &addr);
if (NS_SUCCEEDED(rv)) {
char buf[1024];
NS_FormatCodeAddressDetails(mCallStack[i], &addr, buf, ArrayLength(buf));
fputs(buf, f);
} else {
fprintf(f, "Frame information for %p unavailable", mCallStack[i]);
}
}
}
fflush(f);
}
} }

View File

@ -7,7 +7,6 @@
#define mozilla_DeadlockDetector_h #define mozilla_DeadlockDetector_h
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
#include "mozilla/Move.h"
#include <stdlib.h> #include <stdlib.h>
@ -16,13 +15,30 @@
#include "nsTArray.h" #include "nsTArray.h"
#ifdef NS_TRACE_MALLOC
# include "nsTraceMalloc.h"
#endif // ifdef NS_TRACE_MALLOC
namespace mozilla { namespace mozilla {
// FIXME bug 456272: split this off into a convenience API on top of
// nsStackWalk?
class NS_COM_GLUE CallStack class NS_COM_GLUE CallStack
{ {
private: private:
nsTArray<void*> mCallStack; #ifdef NS_TRACE_MALLOC
typedef nsTMStackTraceID callstack_id;
// needs to be a macro to avoid disturbing the backtrace
# define NS_GET_BACKTRACE() NS_TraceMallocGetStackTrace()
# define NS_DEADLOCK_DETECTOR_CONSTEXPR
#else
typedef void* callstack_id;
# define NS_GET_BACKTRACE() 0
# define NS_DEADLOCK_DETECTOR_CONSTEXPR MOZ_CONSTEXPR
#endif // ifdef NS_TRACE_MALLOC
callstack_id mCallStack;
public: public:
/** /**
@ -37,10 +53,12 @@ public:
* constructor: it *will* construct a backtrace. This can cause * constructor: it *will* construct a backtrace. This can cause
* unexpected performance issues. * unexpected performance issues.
*/ */
CallStack(const nsTArray<void*>& aCallStack = GetBacktrace()) : NS_DEADLOCK_DETECTOR_CONSTEXPR
mCallStack(mozilla::Move(aCallStack)) CallStack(const callstack_id aCallStack = NS_GET_BACKTRACE()) :
mCallStack(aCallStack)
{ {
} }
NS_DEADLOCK_DETECTOR_CONSTEXPR
CallStack(const CallStack& aFrom) : CallStack(const CallStack& aFrom) :
mCallStack(aFrom.mCallStack) mCallStack(aFrom.mCallStack)
{ {
@ -59,19 +77,22 @@ public:
return mCallStack != aOther.mCallStack; return mCallStack != aOther.mCallStack;
} }
bool IsEmpty() const // FIXME bug 456272: if this is split off,
// NS_TraceMallocPrintStackTrace should be modified to print into
// an nsACString
void Print(FILE* f) const
{ {
return mCallStack.IsEmpty(); #ifdef NS_TRACE_MALLOC
if (this != &kNone && mCallStack) {
NS_TraceMallocPrintStackTrace(f, mCallStack);
return;
}
#endif
fputs(" [stack trace unavailable]\n", f);
} }
void Print(FILE* f) const; /** The "null" callstack. */
static const CallStack kNone;
static nsTArray<void*> GetBacktrace();
static const CallStack NullCallStack()
{
return CallStack(nsTArray<void*>());
}
}; };
@ -137,7 +158,7 @@ public:
ResourceAcquisition( ResourceAcquisition(
const T* aResource, const T* aResource,
const CallStack aCallContext=CallStack::NullCallStack()) : const CallStack aCallContext=CallStack::kNone) :
mResource(aResource), mResource(aResource),
mCallContext(aCallContext) mCallContext(aCallContext)
{ {
@ -174,7 +195,7 @@ private:
struct OrderingEntry struct OrderingEntry
{ {
OrderingEntry() : OrderingEntry() :
mFirstSeen(CallStack::NullCallStack()), mFirstSeen(CallStack::kNone),
mOrderedLT() // FIXME bug 456272: set to empirical mOrderedLT() // FIXME bug 456272: set to empirical
{ // dep size? { // dep size?
} }
@ -386,7 +407,7 @@ public:
PLHashEntry* second = *GetEntry(aProposed); PLHashEntry* second = *GetEntry(aProposed);
OrderingEntry* e = static_cast<OrderingEntry*>(second->value); OrderingEntry* e = static_cast<OrderingEntry*>(second->value);
if (e->mFirstSeen.IsEmpty()) if (CallStack::kNone == e->mFirstSeen)
e->mFirstSeen = aCallContext; e->mFirstSeen = aCallContext;
if (!aLast) if (!aLast)

View File

@ -1653,18 +1653,6 @@ public:
nsTArray() {} nsTArray() {}
explicit nsTArray(size_type capacity) : base_type(capacity) {} explicit nsTArray(size_type capacity) : base_type(capacity) {}
explicit nsTArray(const nsTArray& other) : base_type(other) {} explicit nsTArray(const nsTArray& other) : base_type(other) {}
nsTArray(nsTArray&& other) {
this->SwapElements(other);
}
nsTArray& operator=(const nsTArray& other) {
base_type::operator=(other);
return *this;
}
nsTArray& operator=(nsTArray&& other) {
this->SwapElements(other);
return *this;
}
template<class Allocator> template<class Allocator>
explicit nsTArray(const nsTArray_Impl<E, Allocator>& other) : base_type(other) {} explicit nsTArray(const nsTArray_Impl<E, Allocator>& other) : base_type(other) {}