Bug 1182516 - Add Chaos Mode environment variable MOZ_CHAOSMODE. r=roc

This commit is contained in:
Benoit Girard 2015-07-14 17:29:23 -04:00
parent ce65d9290b
commit 2e648924e7
9 changed files with 42 additions and 29 deletions

View File

@ -7,9 +7,11 @@
#include "mozilla/ChaosMode.h"
namespace mozilla {
namespace detail {
Atomic<uint32_t> gChaosModeCounter(0);
ChaosFeature gChaosFeatures = None;
} /* namespace detail */
} /* namespace mozilla */

View File

@ -15,19 +15,7 @@
namespace mozilla {
namespace detail {
extern MFBT_DATA Atomic<uint32_t> gChaosModeCounter;
} // namespace detail
/**
* When "chaos mode" is activated, code that makes implicitly nondeterministic
* choices is encouraged to make random and extreme choices, to test more
* code paths and uncover bugs.
*/
class ChaosMode
{
public:
enum ChaosFeature {
enum ChaosFeature {
None = 0x0,
// Altering thread scheduling.
ThreadScheduling = 0x1,
@ -40,19 +28,32 @@ public:
// Iterate over hash tables in random order.
HashTableIteration = 0x10,
Any = 0xffffffff,
};
};
private:
// Change this to any non-None value to activate ChaosMode.
static const ChaosFeature sChaosFeatures = None;
namespace detail {
extern MFBT_DATA Atomic<uint32_t> gChaosModeCounter;
extern MFBT_DATA ChaosFeature gChaosFeatures;
} // namespace detail
/**
* When "chaos mode" is activated, code that makes implicitly nondeterministic
* choices is encouraged to make random and extreme choices, to test more
* code paths and uncover bugs.
*/
class ChaosMode
{
public:
static void SetChaosFeature(ChaosFeature aChaosFeature)
{
detail::gChaosFeatures = aChaosFeature;
}
static bool isActive(ChaosFeature aFeature)
{
if (detail::gChaosModeCounter > 0) {
return true;
}
return sChaosFeatures & aFeature;
return detail::gChaosFeatures & aFeature;
}
/**

View File

@ -275,7 +275,7 @@ nsSocketTransportService::AddToPollList(SocketContext *sock)
}
uint32_t newSocketIndex = mActiveCount;
if (ChaosMode::isActive(ChaosMode::NetworkScheduling)) {
if (ChaosMode::isActive(ChaosFeature::NetworkScheduling)) {
newSocketIndex = ChaosMode::randomUint32LessThan(mActiveCount + 1);
PodMove(mActiveList + newSocketIndex + 1, mActiveList + newSocketIndex,
mActiveCount - newSocketIndex);

View File

@ -1626,7 +1626,7 @@ nsHttpConnection::OnWriteSegment(char *buf,
return NS_ERROR_FAILURE; // stop iterating
}
if (ChaosMode::isActive(ChaosMode::IOAmounts) &&
if (ChaosMode::isActive(ChaosFeature::IOAmounts) &&
ChaosMode::randomUint32LessThan(2)) {
// read 1...count bytes
count = ChaosMode::randomUint32LessThan(count) + 1;

View File

@ -56,7 +56,7 @@ InsertTransactionSorted(nsTArray<nsHttpTransaction*> &pendingQ, nsHttpTransactio
for (int32_t i=pendingQ.Length()-1; i>=0; --i) {
nsHttpTransaction *t = pendingQ[i];
if (trans->Priority() >= t->Priority()) {
if (ChaosMode::isActive(ChaosMode::NetworkScheduling)) {
if (ChaosMode::isActive(ChaosFeature::NetworkScheduling)) {
int32_t samePriorityCount;
for (samePriorityCount = 0; i - samePriorityCount >= 0; ++samePriorityCount) {
if (pendingQ[i - samePriorityCount]->Priority() != trans->Priority()) {

View File

@ -3123,7 +3123,17 @@ XREMain::XRE_mainInit(bool* aExitFlag)
StartupTimeline::Record(StartupTimeline::MAIN);
if (ChaosMode::isActive(ChaosMode::Any)) {
if (PR_GetEnv("MOZ_CHAOSMODE")) {
ChaosFeature feature = ChaosFeature::Any;
long featureInt = strtol(PR_GetEnv("MOZ_CHAOSMODE"), nullptr, 16);
if (featureInt) {
// NOTE: MOZ_CHAOSMODE=0 or a non-hex value maps to Any feature.
feature = static_cast<ChaosFeature>(featureInt);
}
ChaosMode::SetChaosFeature(feature);
}
if (ChaosMode::isActive(ChaosFeature::Any)) {
printf_stderr("*** You are running in chaos test mode. See ChaosMode.h. ***\n");
}

View File

@ -236,7 +236,7 @@ TimerThread::Run()
if (mSleeping) {
// Sleep for 0.1 seconds while not firing timers.
uint32_t milliseconds = 100;
if (ChaosMode::isActive(ChaosMode::TimerScheduling)) {
if (ChaosMode::isActive(ChaosFeature::TimerScheduling)) {
milliseconds = ChaosMode::randomUint32LessThan(200);
}
waitFor = PR_MillisecondsToInterval(milliseconds);
@ -320,7 +320,7 @@ TimerThread::Run()
// interval is so small we should not wait at all).
double microseconds = (timeout - now).ToMilliseconds() * 1000;
if (ChaosMode::isActive(ChaosMode::TimerScheduling)) {
if (ChaosMode::isActive(ChaosFeature::TimerScheduling)) {
// The mean value of sFractions must be 1 to ensure that
// the average of a long sequence of timeouts converges to the
// actual sum of their times.

View File

@ -95,7 +95,7 @@ nsEventQueue::PutEvent(already_AddRefed<nsIRunnable>&& aRunnable)
// Avoid calling AddRef+Release while holding our monitor.
nsCOMPtr<nsIRunnable> event(aRunnable);
if (ChaosMode::isActive(ChaosMode::ThreadScheduling)) {
if (ChaosMode::isActive(ChaosFeature::ThreadScheduling)) {
// With probability 0.5, yield so other threads have a chance to
// dispatch events to this queue first.
if (ChaosMode::randomUint32LessThan(2)) {

View File

@ -284,7 +284,7 @@ private:
static void
SetupCurrentThreadForChaosMode()
{
if (!ChaosMode::isActive(ChaosMode::ThreadScheduling)) {
if (!ChaosMode::isActive(ChaosFeature::ThreadScheduling)) {
return;
}
@ -926,7 +926,7 @@ nsThread::SetPriority(int32_t aPriority)
pri = PR_PRIORITY_NORMAL;
}
// If chaos mode is active, retain the randomly chosen priority
if (!ChaosMode::isActive(ChaosMode::ThreadScheduling)) {
if (!ChaosMode::isActive(ChaosFeature::ThreadScheduling)) {
PR_SetThreadPriority(mThread, pri);
}