From 2e648924e785134ce5240f20978c6f3b52fba271 Mon Sep 17 00:00:00 2001 From: Benoit Girard Date: Tue, 14 Jul 2015 17:29:23 -0400 Subject: [PATCH] Bug 1182516 - Add Chaos Mode environment variable MOZ_CHAOSMODE. r=roc --- mfbt/ChaosMode.cpp | 2 + mfbt/ChaosMode.h | 41 ++++++++++--------- netwerk/base/nsSocketTransportService2.cpp | 2 +- netwerk/protocol/http/nsHttpConnection.cpp | 2 +- netwerk/protocol/http/nsHttpConnectionMgr.cpp | 2 +- toolkit/xre/nsAppRunner.cpp | 12 +++++- xpcom/threads/TimerThread.cpp | 4 +- xpcom/threads/nsEventQueue.cpp | 2 +- xpcom/threads/nsThread.cpp | 4 +- 9 files changed, 42 insertions(+), 29 deletions(-) diff --git a/mfbt/ChaosMode.cpp b/mfbt/ChaosMode.cpp index d33258f5ce5..48ed093e29b 100644 --- a/mfbt/ChaosMode.cpp +++ b/mfbt/ChaosMode.cpp @@ -7,9 +7,11 @@ #include "mozilla/ChaosMode.h" namespace mozilla { + namespace detail { Atomic gChaosModeCounter(0); +ChaosFeature gChaosFeatures = None; } /* namespace detail */ } /* namespace mozilla */ diff --git a/mfbt/ChaosMode.h b/mfbt/ChaosMode.h index b3a81a2bd95..b5a0b65d0aa 100644 --- a/mfbt/ChaosMode.h +++ b/mfbt/ChaosMode.h @@ -15,8 +15,24 @@ namespace mozilla { +enum ChaosFeature { + None = 0x0, + // Altering thread scheduling. + ThreadScheduling = 0x1, + // Altering network request scheduling. + NetworkScheduling = 0x2, + // Altering timer scheduling. + TimerScheduling = 0x4, + // Read and write less-than-requested amounts. + IOAmounts = 0x8, + // Iterate over hash tables in random order. + HashTableIteration = 0x10, + Any = 0xffffffff, +}; + namespace detail { extern MFBT_DATA Atomic gChaosModeCounter; +extern MFBT_DATA ChaosFeature gChaosFeatures; } // namespace detail /** @@ -27,32 +43,17 @@ extern MFBT_DATA Atomic gChaosModeCounter; class ChaosMode { public: - enum ChaosFeature { - None = 0x0, - // Altering thread scheduling. - ThreadScheduling = 0x1, - // Altering network request scheduling. - NetworkScheduling = 0x2, - // Altering timer scheduling. - TimerScheduling = 0x4, - // Read and write less-than-requested amounts. - IOAmounts = 0x8, - // Iterate over hash tables in random order. - HashTableIteration = 0x10, - Any = 0xffffffff, - }; + static void SetChaosFeature(ChaosFeature aChaosFeature) + { + detail::gChaosFeatures = aChaosFeature; + } -private: - // Change this to any non-None value to activate ChaosMode. - static const ChaosFeature sChaosFeatures = None; - -public: static bool isActive(ChaosFeature aFeature) { if (detail::gChaosModeCounter > 0) { return true; } - return sChaosFeatures & aFeature; + return detail::gChaosFeatures & aFeature; } /** diff --git a/netwerk/base/nsSocketTransportService2.cpp b/netwerk/base/nsSocketTransportService2.cpp index 5b4b5e27725..cc13f3194e8 100644 --- a/netwerk/base/nsSocketTransportService2.cpp +++ b/netwerk/base/nsSocketTransportService2.cpp @@ -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); diff --git a/netwerk/protocol/http/nsHttpConnection.cpp b/netwerk/protocol/http/nsHttpConnection.cpp index 65064795b67..3259fd4f196 100644 --- a/netwerk/protocol/http/nsHttpConnection.cpp +++ b/netwerk/protocol/http/nsHttpConnection.cpp @@ -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; diff --git a/netwerk/protocol/http/nsHttpConnectionMgr.cpp b/netwerk/protocol/http/nsHttpConnectionMgr.cpp index d9ad8b5301f..227d1e816ee 100644 --- a/netwerk/protocol/http/nsHttpConnectionMgr.cpp +++ b/netwerk/protocol/http/nsHttpConnectionMgr.cpp @@ -56,7 +56,7 @@ InsertTransactionSorted(nsTArray &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()) { diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp index d5c8cf9f25a..31b5b19e0e4 100644 --- a/toolkit/xre/nsAppRunner.cpp +++ b/toolkit/xre/nsAppRunner.cpp @@ -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(featureInt); + } + ChaosMode::SetChaosFeature(feature); + } + + if (ChaosMode::isActive(ChaosFeature::Any)) { printf_stderr("*** You are running in chaos test mode. See ChaosMode.h. ***\n"); } diff --git a/xpcom/threads/TimerThread.cpp b/xpcom/threads/TimerThread.cpp index 45e63971f4c..fe7a0d14c41 100644 --- a/xpcom/threads/TimerThread.cpp +++ b/xpcom/threads/TimerThread.cpp @@ -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. diff --git a/xpcom/threads/nsEventQueue.cpp b/xpcom/threads/nsEventQueue.cpp index c0a87a31eed..a725ce23a75 100644 --- a/xpcom/threads/nsEventQueue.cpp +++ b/xpcom/threads/nsEventQueue.cpp @@ -95,7 +95,7 @@ nsEventQueue::PutEvent(already_AddRefed&& aRunnable) // Avoid calling AddRef+Release while holding our monitor. nsCOMPtr 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)) { diff --git a/xpcom/threads/nsThread.cpp b/xpcom/threads/nsThread.cpp index 34bd40a93d8..62b82a36f3c 100644 --- a/xpcom/threads/nsThread.cpp +++ b/xpcom/threads/nsThread.cpp @@ -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); }