Bug 806209 - Prevent the Windows implementation of NS_StackWalk from accessing the stdio APIs in order to avoid deadlocks when profiling on Windows; r=BenWa

--HG--
extra : rebase_source : cb945d9d3cb162a1177029a6aa097af33f7c917b
This commit is contained in:
Ehsan Akhgari 2012-10-29 14:03:01 -04:00
parent 37f89578d7
commit c6c8d4cb2c

View File

@ -306,7 +306,7 @@ WalkStackMain64(struct WalkStackData* data)
// Get a context for the specified thread.
memset(&context, 0, sizeof(CONTEXT));
context.ContextFlags = CONTEXT_FULL;
if (!GetThreadContext(myThread, &context)) {
if (!GetThreadContext(myThread, &context) && data->walkCallingThread) {
PrintError("GetThreadContext");
return;
}
@ -365,7 +365,9 @@ WalkStackMain64(struct WalkStackData* data)
} else {
addr = 0;
spaddr = 0;
PrintError("WalkStack64");
if (data->walkCallingThread) {
PrintError("WalkStack64");
}
}
if (!ok || (addr == 0)) {
@ -473,6 +475,10 @@ NS_StackWalk(NS_WalkStackCallback aCallback, uint32_t aSkipFrames,
targetThread = threadToWalk;
}
// We need to avoid calling fprintf and friends if we're walking the stack of
// another thread, in order to avoid deadlocks.
const bool shouldBeThreadSafe = !!aThread;
// Have to duplicate handle to get a real handle.
if (!myProcess) {
if (!::DuplicateHandle(::GetCurrentProcess(),
@ -480,7 +486,9 @@ NS_StackWalk(NS_WalkStackCallback aCallback, uint32_t aSkipFrames,
::GetCurrentProcess(),
&myProcess,
PROCESS_ALL_ACCESS, FALSE, 0)) {
PrintError("DuplicateHandle (process)");
if (!shouldBeThreadSafe) {
PrintError("DuplicateHandle (process)");
}
return NS_ERROR_FAILURE;
}
}
@ -489,7 +497,9 @@ NS_StackWalk(NS_WalkStackCallback aCallback, uint32_t aSkipFrames,
::GetCurrentProcess(),
&myThread,
THREAD_ALL_ACCESS, FALSE, 0)) {
PrintError("DuplicateHandle (thread)");
if (!shouldBeThreadSafe) {
PrintError("DuplicateHandle (thread)");
}
return NS_ERROR_FAILURE;
}
@ -529,7 +539,7 @@ NS_StackWalk(NS_WalkStackCallback aCallback, uint32_t aSkipFrames,
walkerReturn = ::SignalObjectAndWait(data.eventStart,
data.eventEnd, INFINITE, FALSE);
if (walkerReturn != WAIT_OBJECT_0)
if (walkerReturn != WAIT_OBJECT_0 && !shouldBeThreadSafe)
PrintError("SignalObjectAndWait (1)");
if (data.pc_count > data.pc_size) {
data.pcs = (void**) _alloca(data.pc_count * sizeof(void*));
@ -541,7 +551,7 @@ NS_StackWalk(NS_WalkStackCallback aCallback, uint32_t aSkipFrames,
::PostThreadMessage(gStackWalkThread, WM_USER, 0, (LPARAM)&data);
walkerReturn = ::SignalObjectAndWait(data.eventStart,
data.eventEnd, INFINITE, FALSE);
if (walkerReturn != WAIT_OBJECT_0)
if (walkerReturn != WAIT_OBJECT_0 && !shouldBeThreadSafe)
PrintError("SignalObjectAndWait (2)");
}