diff --git a/toolkit/xre/nsSigHandlers.cpp b/toolkit/xre/nsSigHandlers.cpp index 4c821d7e6d4..98d991e0be9 100644 --- a/toolkit/xre/nsSigHandlers.cpp +++ b/toolkit/xre/nsSigHandlers.cpp @@ -111,7 +111,7 @@ ah_crap_handler(int signum) signum); printf("Stack:\n"); - NS_StackWalk(PrintStackFrame, 2, nsnull); + NS_StackWalk(PrintStackFrame, 2, nsnull, 0); printf("Sleeping for %d seconds.\n",_gdb_sleep_duration); printf("Type 'gdb %s %d' to attach your debugger to this thread.\n", diff --git a/tools/trace-malloc/lib/nsTraceMalloc.c b/tools/trace-malloc/lib/nsTraceMalloc.c index 389d29f2512..de6bca43c4d 100644 --- a/tools/trace-malloc/lib/nsTraceMalloc.c +++ b/tools/trace-malloc/lib/nsTraceMalloc.c @@ -962,7 +962,7 @@ backtrace(tm_thread *t, int skip, int *immediate_abort) /* Walk the stack, even if stacks_enabled is false. We do this to check if we must set immediate_abort. */ info->entries = 0; - rv = NS_StackWalk(stack_callback, skip, info); + rv = NS_StackWalk(stack_callback, skip, info, 0); *immediate_abort = rv == NS_ERROR_UNEXPECTED; if (rv == NS_ERROR_UNEXPECTED || info->entries == 0) { t->suppress_tracing--; @@ -997,7 +997,7 @@ backtrace(tm_thread *t, int skip, int *immediate_abort) /* skip == 0 means |backtrace| should show up, so don't use skip + 1 */ /* NB: this call is repeated below if the buffer is too small */ info->entries = 0; - rv = NS_StackWalk(stack_callback, skip, info); + rv = NS_StackWalk(stack_callback, skip, info, 0); *immediate_abort = rv == NS_ERROR_UNEXPECTED; if (rv == NS_ERROR_UNEXPECTED || info->entries == 0) { t->suppress_tracing--; @@ -1021,7 +1021,7 @@ backtrace(tm_thread *t, int skip, int *immediate_abort) /* and call NS_StackWalk again */ info->entries = 0; - NS_StackWalk(stack_callback, skip, info); + NS_StackWalk(stack_callback, skip, info, 0); /* same stack */ PR_ASSERT(info->entries * 2 == new_stack_buffer_size); diff --git a/xpcom/base/nsStackWalk.cpp b/xpcom/base/nsStackWalk.cpp index c66b059c0b8..7126180a072 100644 --- a/xpcom/base/nsStackWalk.cpp +++ b/xpcom/base/nsStackWalk.cpp @@ -133,7 +133,7 @@ my_malloc_logger(uint32_t type, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, // stack shows up as having two pthread_cond_wait$UNIX2003 frames. const char *name = OnSnowLeopardOrLater() ? "new_sem_from_pool" : "pthread_cond_wait$UNIX2003"; - NS_StackWalk(stack_callback, 0, const_cast(name)); + NS_StackWalk(stack_callback, 0, const_cast(name), 0); } void @@ -802,7 +802,7 @@ WalkStackThread(void* aData) EXPORT_XPCOM_API(nsresult) NS_StackWalk(NS_WalkStackCallback aCallback, PRUint32 aSkipFrames, - void *aClosure) + void *aClosure, uintptr_t aThread) { MOZ_ASSERT(gCriticalAddress.mInit); HANDLE myProcess, myThread; @@ -812,6 +812,13 @@ NS_StackWalk(NS_WalkStackCallback aCallback, PRUint32 aSkipFrames, if (!EnsureImageHlpInitialized()) return false; + HANDLE targetThread; + if (aThread) { + targetThread = reinterpret_cast (aThread); + } else { + targetThread = ::GetCurrentThread(); + } + // Have to duplicate handle to get a real handle. if (!::DuplicateHandle(::GetCurrentProcess(), ::GetCurrentProcess(), @@ -822,7 +829,7 @@ NS_StackWalk(NS_WalkStackCallback aCallback, PRUint32 aSkipFrames, return NS_ERROR_FAILURE; } if (!::DuplicateHandle(::GetCurrentProcess(), - ::GetCurrentThread(), + targetThread, ::GetCurrentProcess(), &myThread, THREAD_ALL_ACCESS, FALSE, 0)) { @@ -1481,9 +1488,10 @@ cs_operate(int (*operate_func)(void *, void *), void * usrarg) EXPORT_XPCOM_API(nsresult) NS_StackWalk(NS_WalkStackCallback aCallback, PRUint32 aSkipFrames, - void *aClosure) + void *aClosure, uintptr_t aThread) { MOZ_ASSERT(gCriticalAddress.mInit); + MOZ_ASSERT(!aThread); struct my_user_args args; if (!initialized) @@ -1561,9 +1569,10 @@ extern void *__libc_stack_end; // from ld-linux.so EXPORT_XPCOM_API(nsresult) NS_StackWalk(NS_WalkStackCallback aCallback, PRUint32 aSkipFrames, - void *aClosure) + void *aClosure, uintptr_t aThread) { MOZ_ASSERT(gCriticalAddress.mInit); + MOZ_ASSERT(!aThread); // Stack walking code courtesy Kipp's "leaky". // Get the frame pointer @@ -1639,9 +1648,10 @@ unwind_callback (struct _Unwind_Context *context, void *closure) EXPORT_XPCOM_API(nsresult) NS_StackWalk(NS_WalkStackCallback aCallback, PRUint32 aSkipFrames, - void *aClosure) + void *aClosure, uintptr_t aThread) { MOZ_ASSERT(gCriticalAddress.mInit); + MOZ_ASSERT(!aThread); unwind_info info; info.callback = aCallback; info.skip = aSkipFrames + 1; @@ -1717,9 +1727,10 @@ NS_FormatCodeAddressDetails(void *aPC, const nsCodeAddressDetails *aDetails, EXPORT_XPCOM_API(nsresult) NS_StackWalk(NS_WalkStackCallback aCallback, PRUint32 aSkipFrames, - void *aClosure) + void *aClosure, uintptr_t aThread) { MOZ_ASSERT(gCriticalAddress.mInit); + MOZ_ASSERT(!aThread); return NS_ERROR_NOT_IMPLEMENTED; } diff --git a/xpcom/base/nsStackWalk.h b/xpcom/base/nsStackWalk.h index 3df812baa33..293e4b59bbb 100644 --- a/xpcom/base/nsStackWalk.h +++ b/xpcom/base/nsStackWalk.h @@ -43,6 +43,7 @@ /* WARNING: This file is intended to be included from C or C++ files. */ #include "nscore.h" +#include PR_BEGIN_EXTERN_C @@ -58,6 +59,10 @@ typedef void * the first callback will be for the caller of * NS_StackWalk. * @param aClosure Caller-supplied data passed through to aCallback. + * @param aThread The thread for which the stack is to be retrieved. + * Passing null causes us to walk the stack of the + * current thread. On Windows, this is a thread HANDLE. + * It is currently not supported on any other platform. * * Returns NS_ERROR_NOT_IMPLEMENTED on platforms where it is * unimplemented. @@ -70,7 +75,7 @@ typedef void */ XPCOM_API(nsresult) NS_StackWalk(NS_WalkStackCallback aCallback, PRUint32 aSkipFrames, - void *aClosure); + void *aClosure, uintptr_t aThread); typedef struct { /* diff --git a/xpcom/base/nsTraceRefcntImpl.cpp b/xpcom/base/nsTraceRefcntImpl.cpp index 77a5cb2d095..9adfcdf4e04 100644 --- a/xpcom/base/nsTraceRefcntImpl.cpp +++ b/xpcom/base/nsTraceRefcntImpl.cpp @@ -883,7 +883,7 @@ static void PrintStackFrame(void *aPC, void *aClosure) void nsTraceRefcntImpl::WalkTheStack(FILE* aStream) { - NS_StackWalk(PrintStackFrame, 2, aStream); + NS_StackWalk(PrintStackFrame, 2, aStream, 0); } //----------------------------------------------------------------------