mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 21:31:04 +00:00
Bug 1366845 - Use XPCOM threads for hang monitor (r=mrbkap)
MozReview-Commit-ID: 3zMWYDATDch
This commit is contained in:
parent
dfcc5830e0
commit
ab129f71c8
@ -110,7 +110,11 @@ class HangMonitorChild
|
||||
|
||||
static HangMonitorChild* Get() { return sInstance; }
|
||||
|
||||
MessageLoop* MonitorLoop() { return mHangMonitor->MonitorLoop(); }
|
||||
void Dispatch(already_AddRefed<nsIRunnable> aRunnable)
|
||||
{
|
||||
mHangMonitor->Dispatch(Move(aRunnable));
|
||||
}
|
||||
bool IsOnThread() { return mHangMonitor->IsOnThread(); }
|
||||
|
||||
private:
|
||||
void ShutdownOnThread();
|
||||
@ -234,7 +238,11 @@ public:
|
||||
*/
|
||||
void UpdateMinidump(uint32_t aPluginId, const nsString& aDumpId);
|
||||
|
||||
MessageLoop* MonitorLoop() { return mHangMonitor->MonitorLoop(); }
|
||||
void Dispatch(already_AddRefed<nsIRunnable> aRunnable)
|
||||
{
|
||||
mHangMonitor->Dispatch(Move(aRunnable));
|
||||
}
|
||||
bool IsOnThread() { return mHangMonitor->IsOnThread(); }
|
||||
|
||||
private:
|
||||
bool TakeBrowserMinidump(const PluginHangData& aPhd, nsString& aCrashId);
|
||||
@ -345,7 +353,7 @@ HangMonitorChild::Shutdown()
|
||||
void
|
||||
HangMonitorChild::ShutdownOnThread()
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(MessageLoop::current() == MonitorLoop());
|
||||
MOZ_RELEASE_ASSERT(IsOnThread());
|
||||
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
mShutdownDone = true;
|
||||
@ -355,19 +363,19 @@ HangMonitorChild::ShutdownOnThread()
|
||||
void
|
||||
HangMonitorChild::ActorDestroy(ActorDestroyReason aWhy)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(MessageLoop::current() == MonitorLoop());
|
||||
MOZ_RELEASE_ASSERT(IsOnThread());
|
||||
|
||||
mIPCOpen = false;
|
||||
|
||||
// We use a task here to ensure that IPDL is finished with this
|
||||
// HangMonitorChild before it gets deleted on the main thread.
|
||||
MonitorLoop()->PostTask(NewNonOwningRunnableMethod(this, &HangMonitorChild::ShutdownOnThread));
|
||||
Dispatch(NewNonOwningRunnableMethod(this, &HangMonitorChild::ShutdownOnThread));
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
HangMonitorChild::RecvTerminateScript()
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(MessageLoop::current() == MonitorLoop());
|
||||
MOZ_RELEASE_ASSERT(IsOnThread());
|
||||
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
mTerminateScript = true;
|
||||
@ -377,7 +385,7 @@ HangMonitorChild::RecvTerminateScript()
|
||||
mozilla::ipc::IPCResult
|
||||
HangMonitorChild::RecvBeginStartingDebugger()
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(MessageLoop::current() == MonitorLoop());
|
||||
MOZ_RELEASE_ASSERT(IsOnThread());
|
||||
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
mStartDebugger = true;
|
||||
@ -387,7 +395,7 @@ HangMonitorChild::RecvBeginStartingDebugger()
|
||||
mozilla::ipc::IPCResult
|
||||
HangMonitorChild::RecvEndStartingDebugger()
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(MessageLoop::current() == MonitorLoop());
|
||||
MOZ_RELEASE_ASSERT(IsOnThread());
|
||||
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
mFinishedStartingDebugger = true;
|
||||
@ -397,7 +405,7 @@ HangMonitorChild::RecvEndStartingDebugger()
|
||||
mozilla::ipc::IPCResult
|
||||
HangMonitorChild::RecvForcePaint(const TabId& aTabId, const uint64_t& aLayerObserverEpoch)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(MessageLoop::current() == MonitorLoop());
|
||||
MOZ_RELEASE_ASSERT(IsOnThread());
|
||||
|
||||
mForcePaintMonitor->NotifyActivity();
|
||||
|
||||
@ -425,7 +433,7 @@ HangMonitorChild::ClearForcePaint()
|
||||
void
|
||||
HangMonitorChild::Bind(Endpoint<PProcessHangMonitorChild>&& aEndpoint)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(MessageLoop::current() == MonitorLoop());
|
||||
MOZ_RELEASE_ASSERT(IsOnThread());
|
||||
|
||||
MOZ_ASSERT(!sInstance);
|
||||
sInstance = this;
|
||||
@ -472,7 +480,7 @@ HangMonitorChild::NotifySlowScript(nsITabChild* aTabChild,
|
||||
}
|
||||
nsAutoCString filename(aFileName);
|
||||
|
||||
MonitorLoop()->PostTask(NewNonOwningRunnableMethod
|
||||
Dispatch(NewNonOwningRunnableMethod
|
||||
<TabId, nsCString>(this,
|
||||
&HangMonitorChild::NotifySlowScriptAsync,
|
||||
id, filename));
|
||||
@ -503,7 +511,7 @@ HangMonitorChild::NotifyPluginHang(uint32_t aPluginId)
|
||||
mSentReport = true;
|
||||
|
||||
// bounce to background thread
|
||||
MonitorLoop()->PostTask(NewNonOwningRunnableMethod<uint32_t>(this,
|
||||
Dispatch(NewNonOwningRunnableMethod<uint32_t>(this,
|
||||
&HangMonitorChild::NotifyPluginHangAsync,
|
||||
aPluginId));
|
||||
}
|
||||
@ -511,7 +519,7 @@ HangMonitorChild::NotifyPluginHang(uint32_t aPluginId)
|
||||
void
|
||||
HangMonitorChild::NotifyPluginHangAsync(uint32_t aPluginId)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(MessageLoop::current() == MonitorLoop());
|
||||
MOZ_RELEASE_ASSERT(IsOnThread());
|
||||
|
||||
// bounce back to parent on background thread
|
||||
if (mIPCOpen) {
|
||||
@ -527,7 +535,7 @@ HangMonitorChild::ClearHang()
|
||||
|
||||
if (mSentReport) {
|
||||
// bounce to background thread
|
||||
MonitorLoop()->PostTask(NewNonOwningRunnableMethod(this, &HangMonitorChild::ClearHangAsync));
|
||||
Dispatch(NewNonOwningRunnableMethod(this, &HangMonitorChild::ClearHangAsync));
|
||||
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
mSentReport = false;
|
||||
@ -540,7 +548,7 @@ HangMonitorChild::ClearHang()
|
||||
void
|
||||
HangMonitorChild::ClearHangAsync()
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(MessageLoop::current() == MonitorLoop());
|
||||
MOZ_RELEASE_ASSERT(IsOnThread());
|
||||
|
||||
// bounce back to parent on background thread
|
||||
if (mIPCOpen) {
|
||||
@ -595,7 +603,7 @@ HangMonitorParent::Shutdown()
|
||||
mProcess = nullptr;
|
||||
}
|
||||
|
||||
MonitorLoop()->PostTask(NewNonOwningRunnableMethod(this,
|
||||
Dispatch(NewNonOwningRunnableMethod(this,
|
||||
&HangMonitorParent::ShutdownOnThread));
|
||||
|
||||
while (!mShutdownDone) {
|
||||
@ -606,7 +614,7 @@ HangMonitorParent::Shutdown()
|
||||
void
|
||||
HangMonitorParent::ShutdownOnThread()
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(MessageLoop::current() == MonitorLoop());
|
||||
MOZ_RELEASE_ASSERT(IsOnThread());
|
||||
|
||||
// mIPCOpen is only written from this thread, so need need to take the lock
|
||||
// here. We'd be shooting ourselves in the foot, because ActorDestroy takes
|
||||
@ -626,15 +634,15 @@ HangMonitorParent::ForcePaint(dom::TabParent* aTab, uint64_t aLayerObserverEpoch
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
if (sShouldForcePaint) {
|
||||
TabId id = aTab->GetTabId();
|
||||
MonitorLoop()->PostTask(NewNonOwningRunnableMethod<TabId, uint64_t>(
|
||||
this, &HangMonitorParent::ForcePaintOnThread, id, aLayerObserverEpoch));
|
||||
Dispatch(NewNonOwningRunnableMethod
|
||||
<TabId, uint64_t>(this, &HangMonitorParent::ForcePaintOnThread, id, aLayerObserverEpoch));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
HangMonitorParent::ForcePaintOnThread(TabId aTabId, uint64_t aLayerObserverEpoch)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(MessageLoop::current() == MonitorLoop());
|
||||
MOZ_RELEASE_ASSERT(IsOnThread());
|
||||
|
||||
if (mIPCOpen) {
|
||||
Unused << SendForcePaint(aTabId, aLayerObserverEpoch);
|
||||
@ -644,14 +652,14 @@ HangMonitorParent::ForcePaintOnThread(TabId aTabId, uint64_t aLayerObserverEpoch
|
||||
void
|
||||
HangMonitorParent::ActorDestroy(ActorDestroyReason aWhy)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(MessageLoop::current() == MonitorLoop());
|
||||
MOZ_RELEASE_ASSERT(IsOnThread());
|
||||
mIPCOpen = false;
|
||||
}
|
||||
|
||||
void
|
||||
HangMonitorParent::Bind(Endpoint<PProcessHangMonitorParent>&& aEndpoint)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(MessageLoop::current() == MonitorLoop());
|
||||
MOZ_RELEASE_ASSERT(IsOnThread());
|
||||
|
||||
DebugOnly<bool> ok = aEndpoint.Bind(this);
|
||||
MOZ_ASSERT(ok);
|
||||
@ -729,7 +737,7 @@ mozilla::ipc::IPCResult
|
||||
HangMonitorParent::RecvHangEvidence(const HangData& aHangData)
|
||||
{
|
||||
// chrome process, background thread
|
||||
MOZ_RELEASE_ASSERT(MessageLoop::current() == MonitorLoop());
|
||||
MOZ_RELEASE_ASSERT(IsOnThread());
|
||||
|
||||
if (!mReportHangs) {
|
||||
return IPC_OK();
|
||||
@ -767,7 +775,7 @@ mozilla::ipc::IPCResult
|
||||
HangMonitorParent::RecvClearHang()
|
||||
{
|
||||
// chrome process, background thread
|
||||
MOZ_RELEASE_ASSERT(MessageLoop::current() == MonitorLoop());
|
||||
MOZ_RELEASE_ASSERT(IsOnThread());
|
||||
|
||||
if (!mReportHangs) {
|
||||
return IPC_OK();
|
||||
@ -787,7 +795,7 @@ HangMonitorParent::RecvClearHang()
|
||||
void
|
||||
HangMonitorParent::TerminateScript()
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(MessageLoop::current() == MonitorLoop());
|
||||
MOZ_RELEASE_ASSERT(IsOnThread());
|
||||
|
||||
if (mIPCOpen) {
|
||||
Unused << SendTerminateScript();
|
||||
@ -797,7 +805,7 @@ HangMonitorParent::TerminateScript()
|
||||
void
|
||||
HangMonitorParent::BeginStartingDebugger()
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(MessageLoop::current() == MonitorLoop());
|
||||
MOZ_RELEASE_ASSERT(IsOnThread());
|
||||
|
||||
if (mIPCOpen) {
|
||||
Unused << SendBeginStartingDebugger();
|
||||
@ -807,7 +815,7 @@ HangMonitorParent::BeginStartingDebugger()
|
||||
void
|
||||
HangMonitorParent::EndStartingDebugger()
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(MessageLoop::current() == MonitorLoop());
|
||||
MOZ_RELEASE_ASSERT(IsOnThread());
|
||||
|
||||
if (mIPCOpen) {
|
||||
Unused << SendEndStartingDebugger();
|
||||
@ -936,7 +944,7 @@ HangMonitoredProcess::TerminateScript()
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
ProcessHangMonitor::Get()->MonitorLoop()->PostTask(NewNonOwningRunnableMethod(mActor,
|
||||
ProcessHangMonitor::Get()->Dispatch(NewNonOwningRunnableMethod(mActor,
|
||||
&HangMonitorParent::TerminateScript));
|
||||
return NS_OK;
|
||||
}
|
||||
@ -953,7 +961,7 @@ HangMonitoredProcess::BeginStartingDebugger()
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
ProcessHangMonitor::Get()->MonitorLoop()->PostTask(NewNonOwningRunnableMethod(mActor,
|
||||
ProcessHangMonitor::Get()->Dispatch(NewNonOwningRunnableMethod(mActor,
|
||||
&HangMonitorParent::BeginStartingDebugger));
|
||||
return NS_OK;
|
||||
}
|
||||
@ -970,7 +978,7 @@ HangMonitoredProcess::EndStartingDebugger()
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
ProcessHangMonitor::Get()->MonitorLoop()->PostTask(NewNonOwningRunnableMethod(mActor,
|
||||
ProcessHangMonitor::Get()->Dispatch(NewNonOwningRunnableMethod(mActor,
|
||||
&HangMonitorParent::EndStartingDebugger));
|
||||
return NS_OK;
|
||||
}
|
||||
@ -1052,9 +1060,7 @@ ProcessHangMonitor::ProcessHangMonitor()
|
||||
obs->AddObserver(this, "xpcom-shutdown", false);
|
||||
}
|
||||
|
||||
mThread = new base::Thread("ProcessHangMonitor");
|
||||
if (!mThread->Start()) {
|
||||
delete mThread;
|
||||
if (NS_FAILED(NS_NewNamedThread("ProcessHangMon", getter_AddRefs(mThread)))) {
|
||||
mThread = nullptr;
|
||||
}
|
||||
}
|
||||
@ -1066,7 +1072,8 @@ ProcessHangMonitor::~ProcessHangMonitor()
|
||||
MOZ_ASSERT(sInstance == this);
|
||||
sInstance = nullptr;
|
||||
|
||||
delete mThread;
|
||||
mThread->Shutdown();
|
||||
mThread = nullptr;
|
||||
}
|
||||
|
||||
ProcessHangMonitor*
|
||||
@ -1129,7 +1136,7 @@ ProcessHangMonitor::ShouldTimeOutCPOWs()
|
||||
void
|
||||
ProcessHangMonitor::InitiateCPOWTimeout()
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(MessageLoop::current() == MonitorLoop());
|
||||
MOZ_RELEASE_ASSERT(IsOnThread());
|
||||
mCPOWTimeout = true;
|
||||
}
|
||||
|
||||
@ -1152,7 +1159,7 @@ CreateHangMonitorParent(ContentParent* aContentParent,
|
||||
auto* process = new HangMonitoredProcess(parent, aContentParent);
|
||||
parent->SetProcess(process);
|
||||
|
||||
monitor->MonitorLoop()->PostTask(NewNonOwningRunnableMethod
|
||||
monitor->Dispatch(NewNonOwningRunnableMethod
|
||||
<Endpoint<PProcessHangMonitorParent>&&>(parent,
|
||||
&HangMonitorParent::Bind,
|
||||
Move(aEndpoint)));
|
||||
@ -1171,16 +1178,23 @@ mozilla::CreateHangMonitorChild(Endpoint<PProcessHangMonitorChild>&& aEndpoint)
|
||||
ProcessHangMonitor* monitor = ProcessHangMonitor::GetOrCreate();
|
||||
auto* child = new HangMonitorChild(monitor);
|
||||
|
||||
monitor->MonitorLoop()->PostTask(NewNonOwningRunnableMethod
|
||||
monitor->Dispatch(NewNonOwningRunnableMethod
|
||||
<Endpoint<PProcessHangMonitorChild>&&>(child,
|
||||
&HangMonitorChild::Bind,
|
||||
Move(aEndpoint)));
|
||||
}
|
||||
|
||||
MessageLoop*
|
||||
ProcessHangMonitor::MonitorLoop()
|
||||
void
|
||||
ProcessHangMonitor::Dispatch(already_AddRefed<nsIRunnable> aRunnable)
|
||||
{
|
||||
return mThread->message_loop();
|
||||
mThread->Dispatch(Move(aRunnable), nsIEventTarget::NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
bool
|
||||
ProcessHangMonitor::IsOnThread()
|
||||
{
|
||||
bool on;
|
||||
return NS_SUCCEEDED(mThread->IsOnCurrentThread(&on)) && on;
|
||||
}
|
||||
|
||||
/* static */ PProcessHangMonitorParent*
|
||||
|
@ -7,16 +7,14 @@
|
||||
#ifndef mozilla_ProcessHangMonitor_h
|
||||
#define mozilla_ProcessHangMonitor_h
|
||||
|
||||
#include "mozilla/AlreadyAddRefed.h"
|
||||
#include "mozilla/Atomics.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIObserver.h"
|
||||
|
||||
class nsIRunnable;
|
||||
class nsITabChild;
|
||||
|
||||
class MessageLoop;
|
||||
|
||||
namespace base {
|
||||
class Thread;
|
||||
} // namespace base
|
||||
class nsIThread;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
@ -66,14 +64,15 @@ class ProcessHangMonitor final
|
||||
void InitiateCPOWTimeout();
|
||||
bool ShouldTimeOutCPOWs();
|
||||
|
||||
MessageLoop* MonitorLoop();
|
||||
void Dispatch(already_AddRefed<nsIRunnable> aRunnable);
|
||||
bool IsOnThread();
|
||||
|
||||
private:
|
||||
static ProcessHangMonitor* sInstance;
|
||||
|
||||
Atomic<bool> mCPOWTimeout;
|
||||
|
||||
base::Thread* mThread;
|
||||
nsCOMPtr<nsIThread> mThread;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
Loading…
Reference in New Issue
Block a user