如何使用WinDBG临界区和线程列表查找线程ID?

时间:2015-03-04 04:58:54

标签: locking windbg

我分析了转储文件以找到锁定的线程,并且我使用了!cs命令。

DebugInfo          = 0x00639610
Critical section   = 0x03e210c8 (+0x3E210C8)
LOCKED
LockCount          = 0x1
WaiterWoken        = No
OwningThread       = 0x000017c8
RecursionCount     = 0x1
LockSemaphore      = 0x5B0
SpinCount          = 0x00000000

此结果表示ThreadID 0x000017c8获得临界区。所以我听了所有线程使用〜命令找到threadID 0x000017c8。

0:000> ~
.  0  Id: 2240.1758 Suspend: 0 Teb: 7efdd000 Unfrozen
   1  Id: 2240.1d90 Suspend: 0 Teb: 7efda000 Unfrozen
   2  Id: 2240.16fc Suspend: 0 Teb: 7efd7000 Unfrozen
   3  Id: 2240.1544 Suspend: 0 Teb: 7ef9c000 Unfrozen
   4  Id: 2240.2550 Suspend: 0 Teb: 7ef99000 Unfrozen
   5  Id: 2240.fd4 Suspend: 0 Teb: 7ef96000 Unfrozen
   6  Id: 2240.1b08 Suspend: 0 Teb: 7ef93000 Unfrozen
   7  Id: 2240.1958 Suspend: 0 Teb: 7ef90000 Unfrozen
   8  Id: 2240.20e8 Suspend: 0 Teb: 7ef8d000 Unfrozen
   9  Id: 2240.1bec Suspend: 0 Teb: 7ef8a000 Unfrozen
  10  Id: 2240.fb4 Suspend: 0 Teb: 7ef87000 Unfrozen
  11  Id: 2240.25c0 Suspend: 0 Teb: 7ef84000 Unfrozen
  12  Id: 2240.15b0 Suspend: 0 Teb: 7ef81000 Unfrozen
  13  Id: 2240.21a8 Suspend: 0 Teb: 7ef7b000 Unfrozen
  14  Id: 2240.1fcc Suspend: 0 Teb: 7ef78000 Unfrozen

但是,没有threadID 0x000017c8。这个转储文件发生了什么?我怎样才能找到线程ID 0x000017c8?

1 个答案:

答案 0 :(得分:2)

Kjell Gunnar是对的:线程17c8因任何原因终止了。

这不仅可以在关键部分发生,也可以在其他同步对象中发生。在我的高级调试培训中,我为参与者提供了ManualResetEvent的类似情况的转储。

这是来源:

#include "stdafx.h"
#include <Windows.h>
#include <process.h>
#include <stdio.h>
#include <iostream>


HANDLE threadA;
HANDLE threadB;
HANDLE eventB;

class WorkItem
{
public:
    virtual void Initialize()
    {
    }
};

unsigned int __stdcall initializeWorkitems(void* param) 
{
    try
    {
        // Initialize workitems
        WorkItem **items = new WorkItem*[2];
        items[0] = new WorkItem();
        items[1] = NULL;

        for (int i = 0; i<2; i++)
        {
                items[i]->Initialize();
        }

        // Signal event for second thread to work on work items
        SetEvent(eventB);
    }
    catch(...)
    {
        // Don't do this
    }
    return 0;
}

unsigned int __stdcall processWorkitems(void* param) 
{
    // Wait for work item initialization to complete
    WaitForSingleObject(eventB, INFINITE);

    // Work on workitems
    Sleep(100);

    return 0;
}


int _tmain(int argc, _TCHAR* argv[])
{
    eventB = CreateEvent(0, 0, 0, 0);

    threadA = (HANDLE)_beginthreadex(0, 0, &initializeWorkitems, (void*)0, 0, 0);
    threadB = (HANDLE)_beginthreadex(0, 0, &processWorkitems, (void*)0, 0, 0);

    WaitForSingleObject(threadA, INFINITE);
    WaitForSingleObject(threadB, INFINITE);

    CloseHandle(threadA);
    CloseHandle(threadB);

    CloseHandle(eventB);

    return 0;
}

在进程挂起时创建转储。分析应该导致与您的关键部分相当的案例。 threadA终止了静默,在catch(...)块中吃了一个NullPointerException,从而永远不会释放手动重置事件。