Bug 1133521 - Enable BHR on Beta. r=vladan

This commit is contained in:
Roberto A. Vitillo 2015-03-09 09:58:00 +01:00
parent c4c85779d8
commit 5820c9e446
4 changed files with 126 additions and 28 deletions

View File

@ -2911,21 +2911,20 @@ TelemetryImpl::GetThreadHangStats(JSContext* cx, JS::MutableHandle<JS::Value> re
}
size_t threadIndex = 0;
#ifdef MOZ_ENABLE_BACKGROUND_HANG_MONITOR
/* First add active threads; we need to hold |iter| (and its lock)
throughout this method to avoid a race condition where a thread can
be recorded twice if the thread is destroyed while this method is
running */
BackgroundHangMonitor::ThreadHangStatsIterator iter;
for (Telemetry::ThreadHangStats* histogram = iter.GetNext();
histogram; histogram = iter.GetNext()) {
JS::RootedObject obj(cx,
CreateJSThreadHangStats(cx, *histogram));
if (!JS_DefineElement(cx, retObj, threadIndex++, obj, JSPROP_ENUMERATE)) {
return NS_ERROR_FAILURE;
if (!BackgroundHangMonitor::IsDisabled()) {
/* First add active threads; we need to hold |iter| (and its lock)
throughout this method to avoid a race condition where a thread can
be recorded twice if the thread is destroyed while this method is
running */
BackgroundHangMonitor::ThreadHangStatsIterator iter;
for (Telemetry::ThreadHangStats* histogram = iter.GetNext();
histogram; histogram = iter.GetNext()) {
JS::RootedObject obj(cx, CreateJSThreadHangStats(cx, *histogram));
if (!JS_DefineElement(cx, retObj, threadIndex++, obj, JSPROP_ENUMERATE)) {
return NS_ERROR_FAILURE;
}
}
}
#endif
// Add saved threads next
MutexAutoLock autoLock(mThreadHangStatsMutex);

View File

@ -9,6 +9,7 @@
#include "mozilla/LinkedList.h"
#include "mozilla/Monitor.h"
#include "mozilla/Move.h"
#include "mozilla/Preferences.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/Telemetry.h"
#include "mozilla/ThreadHangStats.h"
@ -20,16 +21,23 @@
#include "prinrval.h"
#include "prthread.h"
#include "ThreadStackHelper.h"
#include "nsIObserverService.h"
#include "nsIObserver.h"
#include "mozilla/Services.h"
#include "nsXULAppAPI.h"
#include <algorithm>
// Activate BHR only for one every BHR_BETA_MOD users.
#define BHR_BETA_MOD 100;
namespace mozilla {
/**
* BackgroundHangManager is the global object that
* manages all instances of BackgroundHangThread.
*/
class BackgroundHangManager
class BackgroundHangManager : public nsIObserver
{
private:
// Background hang monitor thread function
@ -61,9 +69,11 @@ private:
void RunMonitorThread();
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BackgroundHangManager)
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIOBSERVER
static StaticRefPtr<BackgroundHangManager> sInstance;
static bool sProhibited;
static bool sDisabled;
// Lock for access to members of this class
Monitor mLock;
@ -90,9 +100,23 @@ public:
BackgroundHangManager();
private:
~BackgroundHangManager();
virtual ~BackgroundHangManager();
};
NS_IMPL_ISUPPORTS(BackgroundHangManager, nsIObserver)
NS_IMETHODIMP
BackgroundHangManager::Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData) {
NS_ENSURE_TRUE(!strcmp(aTopic, "profile-after-change"), NS_ERROR_UNEXPECTED);
BackgroundHangMonitor::DisableOnBeta();
nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
MOZ_ASSERT(observerService);
observerService->RemoveObserver(this, "profile-after-change");
return NS_OK;
}
/**
* BackgroundHangThread is a per-thread object that is used
* by all instances of BackgroundHangMonitor to monitor hangs.
@ -162,6 +186,7 @@ public:
StaticRefPtr<BackgroundHangManager> BackgroundHangManager::sInstance;
bool BackgroundHangManager::sProhibited = false;
bool BackgroundHangManager::sDisabled = false;
ThreadLocal<BackgroundHangThread*> BackgroundHangThread::sTlsKey;
@ -421,7 +446,7 @@ BackgroundHangThread::FindThread()
{
#ifdef MOZ_ENABLE_BACKGROUND_HANG_MONITOR
if (BackgroundHangManager::sInstance == nullptr) {
MOZ_ASSERT(BackgroundHangManager::sProhibited,
MOZ_ASSERT(BackgroundHangManager::sProhibited || BackgroundHangManager::sDisabled,
"BackgroundHandleManager is not initialized");
return nullptr;
}
@ -450,6 +475,38 @@ BackgroundHangThread::FindThread()
return nullptr;
}
bool
BackgroundHangMonitor::ShouldDisableOnBeta(const nsCString &clientID) {
MOZ_ASSERT(clientID.Length() == 36, "clientID is invalid");
const char *suffix = clientID.get() + clientID.Length() - 4;
return strtol(suffix, NULL, 16) % BHR_BETA_MOD;
}
bool
BackgroundHangMonitor::IsDisabled() {
#ifdef MOZ_ENABLE_BACKGROUND_HANG_MONITOR
return BackgroundHangManager::sDisabled;
#else
return true;
#endif
}
bool
BackgroundHangMonitor::DisableOnBeta() {
nsAdoptingCString clientID = Preferences::GetCString("toolkit.telemetry.cachedClientID");
bool telemetryEnabled = Preferences::GetBool("toolkit.telemetry.enabled");
if (!telemetryEnabled || !clientID || BackgroundHangMonitor::ShouldDisableOnBeta(clientID)) {
if (XRE_IsParentProcess()) {
BackgroundHangMonitor::Shutdown();
} else {
BackgroundHangManager::sDisabled = true;
}
return true;
}
return false;
}
void
BackgroundHangMonitor::Startup()
@ -457,6 +514,23 @@ BackgroundHangMonitor::Startup()
#ifdef MOZ_ENABLE_BACKGROUND_HANG_MONITOR
MOZ_ASSERT(!BackgroundHangManager::sProhibited, "Prohibited");
MOZ_ASSERT(!BackgroundHangManager::sInstance, "Already initialized");
if (!strcmp(NS_STRINGIFY(MOZ_UPDATE_CHANNEL), "beta")) {
if (XRE_IsParentProcess()) { // cached ClientID hasn't been read yet
ThreadStackHelper::Startup();
BackgroundHangThread::Startup();
BackgroundHangManager::sInstance = new BackgroundHangManager();
nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
MOZ_ASSERT(observerService);
observerService->AddObserver(BackgroundHangManager::sInstance, "profile-after-change", false);
return;
} else if(DisableOnBeta()){
return;
}
}
ThreadStackHelper::Startup();
BackgroundHangThread::Startup();
BackgroundHangManager::sInstance = new BackgroundHangManager();
@ -467,6 +541,11 @@ void
BackgroundHangMonitor::Shutdown()
{
#ifdef MOZ_ENABLE_BACKGROUND_HANG_MONITOR
if (BackgroundHangManager::sDisabled) {
MOZ_ASSERT(!BackgroundHangManager::sInstance, "Initialized");
return;
}
MOZ_ASSERT(!BackgroundHangManager::sProhibited, "Prohibited");
MOZ_ASSERT(BackgroundHangManager::sInstance, "Not initialized");
/* Scope our lock inside Shutdown() because the sInstance object can
@ -475,6 +554,7 @@ BackgroundHangMonitor::Shutdown()
BackgroundHangManager::sInstance->Shutdown();
BackgroundHangManager::sInstance = nullptr;
ThreadStackHelper::Shutdown();
BackgroundHangManager::sDisabled = true;
#endif
}
@ -484,7 +564,7 @@ BackgroundHangMonitor::BackgroundHangMonitor(const char* aName,
: mThread(BackgroundHangThread::FindThread())
{
#ifdef MOZ_ENABLE_BACKGROUND_HANG_MONITOR
if (!BackgroundHangManager::sProhibited && !mThread) {
if (!BackgroundHangManager::sDisabled && !BackgroundHangManager::sProhibited && !mThread) {
// If sProhibit is true, mThread would be null, and no monitoring.
mThread = new BackgroundHangThread(aName, aTimeoutMs, aMaxTimeoutMs);
}
@ -495,6 +575,10 @@ BackgroundHangMonitor::BackgroundHangMonitor()
: mThread(BackgroundHangThread::FindThread())
{
#ifdef MOZ_ENABLE_BACKGROUND_HANG_MONITOR
if (BackgroundHangManager::sDisabled) {
return;
}
MOZ_ASSERT(!BackgroundHangManager::sProhibited || mThread,
"This thread is not initialized for hang monitoring");
#endif
@ -509,7 +593,8 @@ BackgroundHangMonitor::NotifyActivity()
{
#ifdef MOZ_ENABLE_BACKGROUND_HANG_MONITOR
if (mThread == nullptr) {
MOZ_ASSERT(BackgroundHangManager::sProhibited,
MOZ_ASSERT(BackgroundHangManager::sProhibited ||
BackgroundHangManager::sDisabled,
"This thread is not initialized for hang monitoring");
return;
}
@ -525,7 +610,8 @@ BackgroundHangMonitor::NotifyWait()
{
#ifdef MOZ_ENABLE_BACKGROUND_HANG_MONITOR
if (mThread == nullptr) {
MOZ_ASSERT(BackgroundHangManager::sProhibited,
MOZ_ASSERT(BackgroundHangManager::sProhibited ||
BackgroundHangManager::sDisabled,
"This thread is not initialized for hang monitoring");
return;
}
@ -567,7 +653,9 @@ BackgroundHangMonitor::ThreadHangStatsIterator::ThreadHangStatsIterator()
nullptr)
{
#ifdef MOZ_ENABLE_BACKGROUND_HANG_MONITOR
MOZ_ASSERT(BackgroundHangManager::sInstance || BackgroundHangManager::sProhibited,
MOZ_ASSERT(BackgroundHangManager::sInstance ||
BackgroundHangManager::sProhibited ||
BackgroundHangManager::sDisabled,
"Inconsistent state");
#endif
}

View File

@ -10,6 +10,8 @@
#include "mozilla/RefPtr.h"
#include "mozilla/Monitor.h"
#include "nsString.h"
#include <stdint.h>
namespace mozilla {
@ -18,14 +20,8 @@ namespace Telemetry {
class ThreadHangStats;
};
// Disabled for Beta/Release builds because of bug 965392.
// Disabled for debug builds because of bug 979069.
#if !defined(RELEASE_BUILD) && !defined(DEBUG)
// Undefine to disable background hang monitor
#define MOZ_ENABLE_BACKGROUND_HANG_MONITOR
#endif
class BackgroundHangThread;
class BackgroundHangManager;
/**
* The background hang monitor is responsible for detecting and reporting
@ -113,8 +109,13 @@ class BackgroundHangThread;
class BackgroundHangMonitor
{
private:
friend BackgroundHangManager;
RefPtr<BackgroundHangThread> mThread;
static bool ShouldDisableOnBeta(const nsCString &);
static bool DisableOnBeta();
public:
static const uint32_t kNoTimeout = 0;
@ -168,6 +169,11 @@ public:
*/
static void Shutdown();
/**
* Returns true if BHR is disabled.
*/
static bool IsDisabled();
/**
* Start monitoring hangs for the current thread.
*

View File

@ -59,6 +59,11 @@ LOCAL_INCLUDES += [
'/tools/profiler',
]
# BHR disabled for Release builds because of bug 965392.
# BHR disabled for debug builds because of bug 979069.
if CONFIG['MOZ_UPDATE_CHANNEL'] not in ('release') and not CONFIG['MOZ_DEBUG']:
DEFINES['MOZ_ENABLE_BACKGROUND_HANG_MONITOR'] = 1
FAIL_ON_WARNINGS = True
FINAL_LIBRARY = 'xul'