在windbg中分析!threadpool和!threads的输出 [英] Analyzing output of !threadpool and !threads in windbg

查看:380
本文介绍了在windbg中分析!threadpool和!threads的输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在四台服务器上生成了转储,并且正在分析!threadpool和!threads的输出.我注意到以下大致一致的输出:

I have generated dumps on four servers and am analyzing the output of !threadpool and !threads. I noticed the roughly consistent following output:

0:024> !threadpool
CPU utilization 0%
Worker Thread: Total: 2 Running: 0 Idle: 2 MaxLimit: 200 MinLimit: 2
Work Request in Queue: 0
Number of Timers: 27
Completion Port Thread:Total: 2 Free: 0 MaxFree: 4 CurrentLimit: 2 MaxLimit: 200 MinLimit: 2

!threads -special ThreadCount: 32 UnstartedThread: 0 BackgroundThread: 19 PendingThread: 0 DeadThread: 13 Hosted Runtime: no

!threads -special ThreadCount: 32 UnstartedThread: 0 BackgroundThread: 19 PendingThread: 0 DeadThread: 13 Hosted Runtime: no

我的问题是:
1)如何确定这27个计时器的来源?
2)13个死线程是什么意思?
3)我的一个线程被标记为具有锁.如果我切换到该线程并运行!clrstack,则会看到以下内容-与计时器有关吗?

My questions are:
1)How can I determine what the source of those 27 timers are?
2)What does 13 dead threads mean?
3)One of my threads is marked as having a lock. If i switch to that thread and run !clrstack, i see the following - is it related to my timers?


0:027> !clrstack
OS Thread Id: 0x14cc (27)
*** WARNING: Unable to verify checksum for System.ni.dll
Child-SP         RetAddr          Call Site
000000000ca6e1a0 000007fef5c06477 System.Threading.WaitHandle.WaitAny(System.Threading.WaitHandle[], Int32, Boolean)
000000000ca6e200 000007fef673175b System.Net.TimerThread.ThreadProc()
000000000ca6e2d0 000007fef67c95fd System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
000000000ca6e320 000007fef84d1552 System.Threading.ThreadHelper.ThreadStart()

推荐答案

1)如何确定这27个计时器的来源?

尝试查找TimerCallback的实例(对于Threading.Timer):

1)How can I determine what the source of those 27 timers are?

Try to find instances of TimerCallback (for Threading.Timer):

!dumpheap -type TimerCallback

然后转储回调属性(其中,回调地址是dumpheap输出中的地址"):

Then dump the callback properties (where callback address is the "Address" from the dumpheap output):

!do <callback address>

然后转储_target属性的Value地址:

!do <_target address>

那应该吐出持有对TimerCallback的引用的对象,这将带您到创建计时器的地方.

That should spit out the object that holds a reference to the TimerCallback, which should lead you to where the timer was created.

我建议您查看 Tess Ferrandez的调试实验室(如果还没有的话).

I recommend checking out Tess Ferrandez's debugging labs, if you haven't already.

我的理解是,死线程是指C ++线程,该线程不再具有活动的OS线程,而是仍然具有引用,因此无法销毁(C ++线程使用引用计数).

My understanding is that a dead thread refers to a C++ thread which no longer has an active OS thread, but still has references and thus cannot be destroyed (C++ threads use ref counting).

C#线程保留对C ++线程的引用,如果托管代码保留对C#线程的引用,那可能就是您的问题.

A C# thread holds a reference to a C++ thread, and if your managed code keeps a reference to a C# thread, then that could be your problem.

关于Yun Jin博客的帖子可能是对您有些兴趣.

This post on Yun Jin's blog might be of some interest to you.

看起来像(System.Threading)计时器线程正在等待其间隔过去.

That looks like a (System.Threading) timer thread waiting for its interval to elapse.

这篇关于在windbg中分析!threadpool和!threads的输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆