[英]How to get stacktrace for all threads running in a process?
我试图获取运行有多个线程的进程的堆栈跟踪,我能够获取主线程的堆栈跟踪。 但是对于其他线程(属于同一进程),即使我使用了正确的threadIds,我对于所有线程(与主线程相同)也得到相同的stacktrace。 我确信这些不是该线程的正确跟踪。
以下是代码,我不知道出了什么问题。 如果您有任何想法,请告诉我。 谢谢..
我的pExPtrs为null,在异常期间我没有调用此函数。
void DoStackTraces ( LPTSTR szString,DWORD dwSize, EXCEPTION_POINTERS *pExPtrs)
{
HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, static_cast<DWORD>(getpid()));
if (h != INVALID_HANDLE_VALUE)
{
THREADENTRY32 te;
te.dwSize = sizeof(te);
if (Thread32First(h, &te)) {
do {
if (te.dwSize >= FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) +
sizeof(te.th32OwnerProcessID)) {
if(te.th32OwnerProcessID == static_cast<DWORD>(getpid())) {
std::cout << "Process 0x%04x | Thread 0x%04x\n"
<< te.th32OwnerProcessID << " | " << te.th32ThreadID
<< " Current ProcessID : " << getpid()
<< " dwSize : " << dwSize
<< " pExPtrs : " << pExPtrs
<< std::endl;
HANDLE hnd = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, te.th32ThreadID);
SuspendThread(hnd);
DoStackTraceThread(hnd,szString,dwSize,0);
ResumeThread(hnd);
std::cout << szString << std::endl;
}
}
te.dwSize = sizeof(te);
} while (Thread32Next(h, &te));
}
CloseHandle(h);
}
//HANDLE hThread = GetCurrentThread();
//DoStackTraceThread (hThread, szString,dwSize,pExPtrs);
}
void DoStackTraceThread ( HANDLE hThread, LPTSTR szString ,
DWORD dwSize , EXCEPTION_POINTERS *pExPtrs)
{
if (g_bCsysDontGetProcessCritSec){return;}
sAutoLock al(g_stackTraceMux); // The code probably isn't thread safe.
if (g_cSym.isInstalled() == false) return;
HANDLE hProcess = GetCurrentProcess ( ) ;
// If the symbol engine is not initialized, do it now.
if ( FALSE == g_bSymIsInit )
{
DWORD dwOpts = APFSymGetOptions ( ) ;
// Turn on load lines.
APFSymSetOptions ( dwOpts |
SYMOPT_LOAD_LINES ) ;
if ( FALSE == g_cSym.SymInitialize ( hProcess ,
NULL ,
TRUE ) )
{
std::cerr << "APF ERROR: DiagAssert : Unable to initialize the "
"symbol engine!!!" << std::endl;
}
else
{
g_bSymIsInit = TRUE ;
}
}
// The symbol engine is initialized so do the stack walk.
// The array of addresses.
ADDRVECTOR vAddrs ;
// The thread information.
CONTEXT stCtx ;
CONTEXT *pstCtx ;
GET_CURRENT_CONTEXT(stCtx, CONTEXT_FULL);
{
STACKFRAME64 stFrame ;
DWORD dwMachine ;
ZeroMemory ( &stFrame , sizeof ( STACKFRAME64 ) ) ;
stFrame.AddrPC.Mode = AddrModeFlat ;
if (pExPtrs)
{
pstCtx=pExPtrs->ContextRecord;
}
else {
pstCtx=&stCtx;
}
dwMachine = IMAGE_FILE_MACHINE_I386 ;
if (pExPtrs){
stFrame.AddrPC.Offset = pstCtx->Eip ;
stFrame.AddrStack.Offset = pstCtx->Esp ;
stFrame.AddrFrame.Offset = pstCtx->Ebp ;
}
else {
stFrame.AddrPC.Offset = stCtx.Eip ;
stFrame.AddrStack.Offset = stCtx.Esp ;
stFrame.AddrFrame.Offset = stCtx.Ebp ;
}
stFrame.AddrStack.Mode = AddrModeFlat ;
stFrame.AddrFrame.Mode = AddrModeFlat ;
// Loop for the first 512 stack elements.
for ( DWORD i = 0 ; i < 512 ; i++ )
{
if ( FALSE == StackWalkProc ( dwMachine ,
hProcess ,
hThread ,
&stFrame ,
pstCtx ,
NULL ,
(PFUNCTION_TABLE_ACCESS_ROUTINE64)
APFSymFunctionTableAccess ,
GetModBase ,
NULL ) )
{
break ;
}
// Also check that the address is not zero. Sometimes
// StackWalk returns TRUE with a frame of zero.
if ( 0 != stFrame.AddrPC.Offset )
{
vAddrs.push_back ( stFrame.AddrPC.Offset ) ;
}
}
// Now start converting the addresses.
DWORD64 dwSizeLeft = dwSize ;
DWORD64 dwSymSize ;
TCHAR szSym [ MAX_PATH * 2 ] ;
LPTSTR szCurrPos = szString ;
ADDRVECTOR::iterator loop ;
for ( loop = vAddrs.begin ( ) ;
loop != vAddrs.end ( ) ;
loop++ )
{
dwSymSize = DoConvertAddress ( *loop , szSym ) ;
if ( dwSizeLeft <= dwSymSize )
{
break ;
}
_tcscpy ( szCurrPos , szSym ) ;
szCurrPos += dwSymSize ;
dwSizeLeft -= dwSymSize ;
}
}
}
线程快照的句柄与线程快照的句柄不同。 在快照句柄上调用Suspend / ResumeThread是错误的(如果不是这样,则可能很危险,如果您将此线程SuspendThread呢?)。 您需要使用带有线程ID的OpenThread来获取可与StackWalk64一起使用的句柄。
同样,假设GET_CURRENT_CONTEXT在当前线程上运行,那将是不正确的。 如果它在hnd上工作,它将再次不起作用,因为再次,那不是线程句柄。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.