зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1302914 - Use GetThreadContext after calling SuspendThread to ensure threads are really suspended. r=froydnj
This commit is contained in:
Родитель
fe16e1f10c
Коммит
e079cbfe2a
|
@ -193,6 +193,22 @@ class SamplerThread : public Thread {
|
|||
if (SuspendThread(profiled_thread) == kSuspendFailed)
|
||||
return;
|
||||
|
||||
// SuspendThread is asynchronous, so the thread may still be running.
|
||||
// Call GetThreadContext first to ensure the thread is really suspended.
|
||||
// See https://blogs.msdn.microsoft.com/oldnewthing/20150205-00/?p=44743.
|
||||
|
||||
// Using only CONTEXT_CONTROL is faster but on 64-bit it causes crashes in
|
||||
// RtlVirtualUnwind (see bug 1120126) so we set all the flags.
|
||||
#if V8_HOST_ARCH_X64
|
||||
context.ContextFlags = CONTEXT_FULL;
|
||||
#else
|
||||
context.ContextFlags = CONTEXT_CONTROL;
|
||||
#endif
|
||||
if (!GetThreadContext(profiled_thread, &context)) {
|
||||
ResumeThread(profiled_thread);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef MOZ_STACKWALKING
|
||||
// Threads that may invoke JS require extra attention. Since, on windows,
|
||||
// the jits also need to modify the same dynamic function table that we need
|
||||
|
@ -218,26 +234,19 @@ class SamplerThread : public Thread {
|
|||
}
|
||||
#endif
|
||||
|
||||
// Using only CONTEXT_CONTROL is faster but on 64-bit it causes crashes in
|
||||
// RtlVirtualUnwind (see bug 1120126) so we set all the flags.
|
||||
#if V8_HOST_ARCH_X64
|
||||
context.ContextFlags = CONTEXT_FULL;
|
||||
sample->pc = reinterpret_cast<Address>(context.Rip);
|
||||
sample->sp = reinterpret_cast<Address>(context.Rsp);
|
||||
sample->fp = reinterpret_cast<Address>(context.Rbp);
|
||||
#else
|
||||
context.ContextFlags = CONTEXT_CONTROL;
|
||||
sample->pc = reinterpret_cast<Address>(context.Eip);
|
||||
sample->sp = reinterpret_cast<Address>(context.Esp);
|
||||
sample->fp = reinterpret_cast<Address>(context.Ebp);
|
||||
#endif
|
||||
if (GetThreadContext(profiled_thread, &context) != 0) {
|
||||
#if V8_HOST_ARCH_X64
|
||||
sample->pc = reinterpret_cast<Address>(context.Rip);
|
||||
sample->sp = reinterpret_cast<Address>(context.Rsp);
|
||||
sample->fp = reinterpret_cast<Address>(context.Rbp);
|
||||
#else
|
||||
sample->pc = reinterpret_cast<Address>(context.Eip);
|
||||
sample->sp = reinterpret_cast<Address>(context.Esp);
|
||||
sample->fp = reinterpret_cast<Address>(context.Ebp);
|
||||
#endif
|
||||
sample->context = &context;
|
||||
sampler->Tick(sample);
|
||||
}
|
||||
|
||||
sample->context = &context;
|
||||
sampler->Tick(sample);
|
||||
|
||||
ResumeThread(profiled_thread);
|
||||
}
|
||||
|
||||
|
|
|
@ -158,13 +158,29 @@ GetChromeHangReport(Telemetry::ProcessedStack& aStack,
|
|||
AcquireStackWalkWorkaroundLock();
|
||||
#endif
|
||||
DWORD ret = ::SuspendThread(winMainThreadHandle);
|
||||
bool suspended = false;
|
||||
if (ret != -1) {
|
||||
// SuspendThread is asynchronous, so the thread may still be running. Use
|
||||
// GetThreadContext to ensure it's really suspended.
|
||||
// See https://blogs.msdn.microsoft.com/oldnewthing/20150205-00/?p=44743.
|
||||
CONTEXT context;
|
||||
context.ContextFlags = CONTEXT_CONTROL;
|
||||
if (::GetThreadContext(winMainThreadHandle, &context)) {
|
||||
suspended = true;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _WIN64
|
||||
ReleaseStackWalkWorkaroundLock();
|
||||
#endif
|
||||
|
||||
if (ret == -1) {
|
||||
if (!suspended) {
|
||||
if (ret != -1) {
|
||||
MOZ_ALWAYS_TRUE(::ResumeThread(winMainThreadHandle) != DWORD(-1));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
MozStackWalk(ChromeStackWalker, /* skipFrames */ 0, /* maxFrames */ 0,
|
||||
reinterpret_cast<void*>(&rawStack),
|
||||
reinterpret_cast<uintptr_t>(winMainThreadHandle), nullptr);
|
||||
|
|
|
@ -247,8 +247,15 @@ ThreadStackHelper::GetStack(Stack& aStack)
|
|||
return;
|
||||
}
|
||||
|
||||
FillStackBuffer();
|
||||
FillThreadContext();
|
||||
// SuspendThread is asynchronous, so the thread may still be running. Use
|
||||
// GetThreadContext to ensure it's really suspended.
|
||||
// See https://blogs.msdn.microsoft.com/oldnewthing/20150205-00/?p=44743.
|
||||
CONTEXT context;
|
||||
context.ContextFlags = CONTEXT_CONTROL;
|
||||
if (::GetThreadContext(mThreadID, &context)) {
|
||||
FillStackBuffer();
|
||||
FillThreadContext();
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_TRUE(::ResumeThread(mThreadID) != DWORD(-1));
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче