--- title: windbg使用教程_程序卡住记录 tags: - windbg cover: 'https://picsum.photos/400' abbrlink: 92059dae date: 2024-07-27 20:19:56 --- \`\`\`bash !eeversion --鉴别下程序的类型 \`\`\` net4.0 32位程序 加载sos。如果是net core,需要安装 SOS dotnet-sos \[使用 Store 版的 WinDbg 调试 .NET 应用 - 冠军 - 博客园 (cnblogs.com)\](https://www.cnblogs.com/haogj/p/18256142) \`\`\`bash 0:000\> .load C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\SOS.dll \`\`\` 自己的程序有pdb,配置一下pdb windbg preview 使用 crtl+alt+s debug设置浏览目录,这个有进入debug状态才能配置? \`\`\`bash srv\* C:\\Users\\yayi\\Desktop\\DUMP\\Test\\Debug \`\`\` 加载sos之后可以!sos.help,查看sos支持哪些命令。 扩展命令使用 ! 作为引导符号。 执行 \`!soshelp\` 或者 \`!sos.help\` 来查看现在支持的 SOS 扩展命令 存活时间 \[!runaway (WinDbg) - Windows 驱动程序\|微软学习 --- !runaway (WinDbg) - Windows drivers \| Microsoft Learn\](https://learn.microsoft.com/en-us/windows-hardware/drivers/debuggercmds/-runaway) \`\`\`bash !runaway 0x4 \`\`\` \`\`\`bash Elapsed Time Thread Time 0:27b4 0 days 0:58:52.469 1:3b58 0 days 0:58:52.047 2:119c 0 days 0:58:52.043 3:2a84 0 days 0:58:51.994 4:331c 0 days 0:58:51.979 5:2a38 0 days 0:58:51.911 6:3558 0 days 0:58:51.802 7:1508 0 days 0:58:51.671 8:3774 0 days 0:58:51.603 9:268 0 days 0:58:51.599 \`\`\` 用户态运行时间 \`\`\`bash !runaway 0x1 \`\`\` \`\`\`bash User Mode Time Thread Time 9:268 0 days 0:58:30.843 8:3774 0 days 0:58:28.640 4:331c 0 days 0:00:00.281 0:27b4 0 days 0:00:00.109 7:1508 0 days 0:00:00.031 6:3558 0 days 0:00:00.000 5:2a38 0 days 0:00:00.000 3:2a84 0 days 0:00:00.000 2:119c 0 days 0:00:00.000 1:3b58 0 days 0:00:00.000 \`\`\` 注:\[理解Elapsed Time、CPU Time、Wait Time-CSDN博客\](https://blog.csdn.net/xingjingb/article/details/121887673) #### Elapsed Time Elapsed Time、CPU Time、Wait Time的关系 在单核处理器的情况下,Elapsed Time = Cpu Time + Wait Time。 在多核处理器的情况下,由于多个CPU同时处理任务所以可能会出现Cpu Time 大于Elapsed Time 的情况。 观察线程情况: \`\`\`bash !t \`\`\` \`\`\`bash 0:000\> !t ThreadCount: 13 UnstartedThread: 0 BackgroundThread: 7 PendingThread: 0 DeadThread: 5 Hosted Runtime: no Lock ID OSID ThreadOBJ State GC Mode GC Alloc Context Domain Count Apt Exception 0 1 27b4 01555df0 26020 Preemptive 0235E39C:00000000 0154f7b8 0 STA 2 2 119c 015641d8 2b220 Preemptive 02210DD8:00000000 0154f7b8 0 MTA (Finalizer) 4 3 331c 015daba8 2b220 Preemptive 00000000:00000000 0154f7b8 0 MTA 5 4 2a38 015e93f8 8029220 Preemptive 00000000:00000000 0154f7b8 0 MTA (Threadpool Completion Port) 6 5 3558 0e5d7ac0 102a220 Preemptive 00000000:00000000 0154f7b8 0 MTA (Threadpool Worker) 7 6 1508 0162d000 202b220 Preemptive 023729F4:00000000 0154f7b8 0 MTA 8 7 3774 0e5e2a98 2b220 Cooperative 00000000:00000000 0154f7b8 0 MTA 9 8 268 0e5ea7f0 2b220 Cooperative 00000000:00000000 0154f7b8 0 MTA XXXX 21 0 0e626438 1039820 Preemptive 00000000:00000000 0154f7b8 0 Ukn (Threadpool Worker) XXXX 20 0 0e624f18 1039820 Preemptive 00000000:00000000 0154f7b8 0 Ukn (Threadpool Worker) XXXX 19 0 0e626980 1039820 Preemptive 00000000:00000000 0154f7b8 0 Ukn (Threadpool Worker) XXXX 18 0 0e624488 1039820 Preemptive 00000000:00000000 0154f7b8 0 Ukn (Threadpool Worker) XXXX 17 0 0e6259a8 1039820 Preemptive 00000000:00000000 0154f7b8 0 Ukn (Threadpool Worker) \`\`\` kb 查看线程 \*\*b:显示栈上的前三个参数(不一定是参数,仅仅是三个固定位置的值)\*\* 找到线程?不知道第三个列显示的是什么,感觉找不到哪个是我要用的。 ===》dump目前处于主线程:输k或者kb会显示当前线程堆栈,目前GUI应该一般在主线程。 kb 4 指的是显示前4行信息。 \~\*e !clrstack 用这个确认一下,显示所有线程堆栈,可以看到我们要的信息在4号线程。 \`\`\`bash \`\`\` \[k、kb、kc、kd、kp、kP、kv(显示堆栈回溯)- Windows 驱动程序 \| k、kb、kc、kd、kp、kP、kv(显示堆栈回溯)微软学习 --- k, kb, kc, kd, kp, kP, kv (Display Stack Backtrace) - Windows drivers \| Microsoft Learn\](https://learn.microsoft.com/en-us/windows-hardware/drivers/debuggercmds/k--kb--kc--kd--kp--kp--kv--display-stack-backtrace-) \`\`\`bash 0:000\> kb # ChildEBP RetAddr Args to Child 00 012fefe4 5aff7a6e 9b62ca40 644a0e18 012ff1f8 win32u!NtUserWaitMessage+0xc 01 012fefe4 5aff7473 00000000 00000000 00000000 System_Windows_Forms_ni!System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop+0x45a 02 012ff038 5aff72e0 00000000 00000000 00000000 System_Windows_Forms_ni!System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner+0x15f 03 012ff064 5afcb7a5 00000000 00000000 00000000 System_Windows_Forms_ni!System.Windows.Forms.Application.ThreadContext.RunMessageLoop+0x4c 04 012ff07c 019c048b 00000000 00000000 00000000 System_Windows_Forms_ni!System.Windows.Forms.Application.Run+0x31 05 012ff088 644a0096 00000000 00000000 00000000 DMT!DMT.Program.Main+0x43 \[C:\\Users\\d\\Program.cs @ 18\] 06 012ff094 644a3210 012ff124 012ff0d8 64634b30 clr!CallDescrWorkerInternal+0x34 07 012ff0e8 644a8dc4 00000000 00000000 00000001 clr!CallDescrWorkerWithHandler+0x6b \`\`\` 源代码在手,4号线程是问题线程,切换线程 \`\`\`bash \~04s \`\`\` 显示托管线程栈 \`\`\`bash !clrstack \`\`\` \`\`\`bash 0:004\> !clrstack The version of SOS does not match the version of CLR you are debugging. Please load the matching version of SOS for the version of CLR you are debugging. CLR Version: 4.7.4101.0 SOS Version: 4.8.9256.0 OS Thread Id: 0x331c (4) Child SP IP Call Site 0621f1c4 771cee5c \[InlinedCallFrame: 0621f1c4\] 0621f1a4 0ee71dc8 DomainBoundILStubClass.IL_STUB_PInvoke(IntPtr, IntPtr, IntPtr, IntPtr ByRef, Oracle.DataAccess.Client.OpoSqlValCtx\*, Oracle.DataAccess.Client.OpoMetValCtx\*, Oracle.DataAccess.Client.OpoDacValCtx\*) 0621f1c4 0ee71757 \[InlinedCallFrame: 0621f1c4\] Oracle.DataAccess.Client.OpsDac.Read(IntPtr, IntPtr, IntPtr, IntPtr ByRef, Oracle.DataAccess.Client.OpoSqlValCtx\*, Oracle.DataAccess.Client.OpoMetValCtx\*, Oracle.DataAccess.Client.OpoDacValCtx\*) 0621f20c 0ee71757 Oracle.DataAccess.Client.OracleDataReader.Read() 0621f244 5d00fd70 System.Data.Common.DataAdapter.FillLoadDataRow(System.Data.ProviderBase.SchemaMapping) 0621f278 5d00fb26 System.Data.Common.DataAdapter.FillFromReader(System.Data.DataSet, System.Data.DataTable, System.String, System.Data.ProviderBase.DataReaderContainer, Int32, Int32, System.Data.DataColumn, System.Object) 0621f2cc 5d00f757 System.Data.Common.DataAdapter.Fill(System.Data.DataSet, System.String, System.Data.IDataReader, Int32, Int32) 0621f30c 0ebcf3f3 Oracle.DataAccess.Client.OracleDataAdapter.Fill(System.Data.DataSet, System.String, System.Data.IDataReader, Int32, Int32) 0621f3dc 0ebca922 Oracle.DataAccess.Client.OracleDataAdapter.Fill(System.Data.DataSet, Int32, Int32, System.String, System.Data.IDbCommand, System.Data.CommandBehavior) 0621f434 5d09e987 System.Data.Common.DbDataAdapter.Fill(System.Data.DataSet, System.String) 0621f468 0ebc8f1b OracleService.ExecuteQue \`\`\` 显示非托管和托管堆栈: \`!DumpStack\` will include "dead"/"abandoned" frames a\`!DumpStack\` 就会包含"死亡"/"废弃"帧?\[SOS debugging extension for .NET - .NET \| Microsoft Learn\](https://learn.microsoft.com/en-us/dotnet/core/diagnostics/sos-debugging-extension) \`\`\`bash !dumpsstack \`\`\` \| \*\*DumpStack\*\* \[\*\*-EE\*\*\] \[\*\*-n\*\*\] \[\`top\` \*stack\* \[\`bottom\` \*stack\*\]\] \| Displays a stack trace.
The \*\*-EE\*\* option causes the \*\*DumpStack\*\* command to display only managed functions. Use the \`top\` and \`bottom\` parameters to limit the stack frames displayed on x86 platforms.
The \*\*-n\*\* option disables the display of source file names and line numbers. If the debugger has the option SYMOPT_LOAD_LINES specified, SOS will look up the symbols for every managed frame and if successful will display the corresponding source file name and line number. The \*\*-n\*\* (No line numbers) parameter can be specified to disable this behavior. \| \| ------------------------------------------------------------------- \| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- \| \*\*kp:\*\* \`\`\`bash kp \`\`\` WARNING: Stack unwind information not available. Following frames may be wrong. 好像也不准 \`\`\`bash 0:004\> kp # ChildEBP RetAddr 00 062191d8 7254a6c9 ntdll!NtWaitForSingleObject+0xc 01 062191d8 725530dc mswsock!SockWaitForSingleObject+0x139 02 0621924c 75e0385e mswsock!WSPRecv+0x864c 03 0621929c 07601b3b ws2_32!WSARecv+0x11e \`\`\` !SockWaitForSingleObj sock oracle 发起连接数据库。 加载一下sosex扩展\[一次有教益的程序崩溃调试 (上) - liangshi - 博客园 (cnblogs.com)\](https://www.cnblogs.com/liangshi/archive/2010/09/05/1818554.html) \[WinDbg: SOSEX 下载,加载和使用帮助 - 冠军 - 博客园 (cnblogs.com)\](https://www.cnblogs.com/haogj/p/18258451) \`\`\`bash .load D:\\windbg\\sosex_32\\sosex.dll \`\`\` sosex的!mk可以同时查看托管栈帧和非托管栈帧, M标记了托管栈帧,U标记了非托管栈帧。 \`\`\`bash 0:004\> !mk Thread 4: SP IP 00:U 06219178 771cee5c ntdll!NtWaitForSingleObject+0xc 01:U 0621917c 7254a6c9 mswsock!SockWaitForSingleObject+0x139 02:U 062191e0 725530dc mswsock!WSPRecv+0x864c 03:U 06219254 75e0385e ws2_32!WSARecv+0x11e 04:U 062192a4 07601b3b OraOCIEI11!slfipsbs+0xdacf 05:U 062192e0 07a747bd OraOCIEI11!k2mdii+0x79a9b 06:U 062193e8 0779e780 OraOCIEI11!sltsthndinit+0x8673c 07:U 0621951c 0779effb OraOCIEI11!sltsthndinit+0x86fb7 08:U 06219538 07759a1d OraOCIEI11!sltsthndinit+0x419d9 09:U 06219658 068b1a18 OraOCIEI11!sigpidu+0x916 0a:U 06219f10 07804494 OraOCIEI11!sltsthndinit+0xec450 0b:U 06219f28 067ca260 OraOCIEI11!kpummGetTZI+0x1072 0c:U 0621c254 071cd628 OraOCIEI11!upidbg+0x416 0d:U 0621c288 07261690 OraOCIEI11!kpurcsc+0x5a 0e:U 0621c2c0 071cb7d5 OraOCIEI11!upibnchr+0x16c37 0f:U 0621e624 071cafe4 OraOCIEI11!upibnchr+0x16446 10:U 0621e6a0 070d126d OraOCIEI11!OCIStmtFetch+0x1d 11:U 0621e6c0 10079710 oci!OCIStmtFetch+0x38 12:U 0621f114 06563b1e OraOps11w+0x3b1e 13:U 0621f140 06567297 OraOps11w+0x7297 14:U 0621f170 06576122 OraOps11w!OpsDacRead+0x272 15:M 0621f1a4 0ee71dc8 DomainBoundILStubClass.IL_STUB_PInvoke(IntPtr, IntPtr, IntPtr, IntPtr ByRef, Oracle.DataAccess.Client.OpoSqlValCtx\*, Oracle.DataAccess.Client.OpoMetValCtx\*, Oracle.DataAccess.Client.OpoDacValCtx\*) 16:M 0621f20c 0ee71757 Oracle.DataAccess.Client.OracleDataReader.Read()(+0x4c2 IL,+0x687 Native) 17:M 0621f244 5d00fd70 System.Data.Common.DataAdapter.FillLoadDataRow(System.Data.ProviderBase.SchemaMapping)(+0x56 IL,+0xd4 Native) 18:M 0621f278 5d00fb26 System.Data.Common.DataAdapter.FillFromReader(System.Data.DataSet, System.Data.DataTable, System.String, System.Data.ProviderBase.DataReaderContainer, Int32, Int32, System.Data.DataColumn, System.Object)(+0x65 IL,+0xc6 Native) 19:M 0621f2cc 5d00f757 System.Data.Common.DataAdapter.Fill(System.Data.DataSet, System.String, System.Data.IDataReader, Int32, Int32)(+0x89 IL,+0x19b Native) 1a:M 0621f30c 0ebcf3f3 Oracle.DataAccess.Client.OracleDataAdapter.Fill(System.Data.DataSet, System.String, System.Data.IDataReader, Int32, Int32)(+0x112 IL,+0x2a3 Native) 1b:M 0621f3dc 0ebca922 Oracle.DataAccess.Client.OracleDataAdapter.Fill(System.Data.DataSet, Int32, Int32, System.String, System.Data.IDbCommand, System.Data.CommandBehavior)(+0xe0 IL,+0x162 Native) 1c:M 0621f434 5d09e987 System.Data.Common.DbDataAdapter.Fill(System.Data.DataSet, System.String)(+0x2d IL,+0x57 Native) 1d:M 0621f468 0ebc8f1b \*\*\* WARNING: Unable to verify checksum for IOracleHelper.dll OracleService.ExecuteQuery(System.String)(+0x7a IL,+0x1cb Native) \`\`\` 文心一言 ai:回答的结果:ai nb(信息聚合): 不过这个调用栈回答的顺序错了 从您提供的堆栈跟踪(stack trace)中,我们可以看到一个关于Oracle数据库操作的线程在执行过程中遇到的调用栈。这里是一个简要的解释和可能的问题点: 1. \*\*线程状态\*\*:线程正在执行(由\`U\`表示用户模式,\`M\`表示混合模式,即托管代码和非托管代码的混合)。 2. \*\*调用栈\*\*: - 从\`ntdll!NtWaitForSingleObject\`开始,这是Windows内核中的一个API,用于等待单个对象(如事件、互斥体、信号量等)变为信号状态。这表明线程在某个点正在等待某个资源。 - 接着调用进入了\`mswsock\`(Windows Sockets 2 Service Provider),表明网络操作正在发生。\`SockWaitForSingleObject\`和\`WSPRecv\`表明线程在等待网络数据。 - 随后,调用进入了\`ws2_32!WSARecv\`,这是Windows Sockets API的一部分,用于从套接字接收数据。 - 接着是Oracle的OCI(Oracle Call Interface)库中的多个函数调用,如\`OraOCIEI11!k2mdii\`、\`OraOCIEI11!sltsthndinit\`等,这些函数通常与Oracle数据库的高级交互有关,如会话处理、语句执行等。 - 最终,调用进入了\`Oracle.DataAccess.Client.OracleDataReader.Read()\`,这是.NET环境中Oracle数据提供程序的一部分,用于从Oracle数据库读取数据。 3. \*\*可能的问题\*\*: - \*\*网络延迟或问题\*\*:由于调用栈中涉及\`WSARecv\`和\`SockWaitForSingleObject\`,这表明线程正在等待网络数据。如果数据没有按预期到达,可能是因为网络延迟、网络分区或Oracle服务器响应慢等问题。 - \*\*Oracle服务器问题\*\*:如果Oracle服务器负载高或配置不当,也可能导致响应延迟或失败。 - \*\*客户端配置\*\*:检查Oracle客户端的配置,确保所有必要的连接设置(如连接字符串、超时设置等)都已正确配置。 - \*\*资源竞争或死锁\*\*:如果Oracle数据库中存在资源竞争或死锁,也可能导致查询或操作被阻塞。 4. \*\*调试建议\*\*: - \*\*检查网络\*\*:使用网络工具(如ping、traceroute等)检查网络连接。 - \*\*查看Oracle日志\*\*:检查Oracle数据库的日志文件,以获取有关可能错误的更多信息。 - \*\*增加超时\*\*:如果问题是由于网络延迟,考虑在应用程序中增加数据库操作的超时时间。 - \*\*代码审查\*\*:审查与数据库交互的代码,确保没有导致资源泄露或不必要的长时间等待的代码。 - \*\*使用性能分析工具\*\*:使用性能分析工具(如Visual Studio的诊断工具、SQL Server Profiler的Oracle版本等)来跟踪和诊断性能问题。 确实,调用栈(Call Stack)的展示方式通常是从下往上,即最底部的调用是最先发生的,而顶部的调用是最近发生的。在您提供的堆栈跟踪中,由于是从上到下列出的,我们需要将其反转来理解执行顺序。 将您的堆栈跟踪从下往上重新排列后,它应该类似于这样(为了简化,我省略了某些中间层,并假设了大致的调用顺序): \`\`\` 1a:M 0ebcf3f3 Oracle.DataAccess.Client.OracleDataReader的某个方法(可能是处理读取结果或类似操作) 19:M 5d00f757 System.Data.Common.DataAdapter的Fill方法(调用OracleDataReader来填充DataSet) 18:M 5d00fb26 System.Data.Common.DataAdapter的FillFromReader方法(从DataReader中读取数据并填充到DataTable或DataSet中) 17:M 5d00fd70 System.Data.Common.DataAdapter的FillLoadDataRow方法(处理从DataReader读取的每一行数据) 16:M 0ee71757 Oracle.DataAccess.Client.OracleDataReader的Read方法(从Oracle数据库读取下一行数据) 15:M 0ee71dc8 DomainBoundILStubClass的IL_STUB_PInvoke方法(P/Invoke调用,用于从托管代码调用非托管Oracle客户端库) 14:U 06576122 OraOps11w!OpsDacRead(Oracle数据访问组件中的某个方法) 13:U 06567297 OraOps11w中的某个方法(可能是OpsDacRead的调用者) 12:U 10079710 oci!OCIStmtFetch(OCI层中的Fetch操作,用于从Oracle数据库中检索数据) 11:U 070d126d OraOCIEI11!OCIStmtFetch(Oracle客户端库中的Fetch操作实现) 10:U 071cafe4 OraOCIEI11!upibnchr+0x16446(Oracle内部处理,可能与网络或数据解析相关) ...(省略了中间的一些调用,因为它们通常涉及更底层的Oracle库实现细节) 05:U 062192e0 OraOCIEI11!k2mdii+0x79a9b(Oracle客户端库中的某个方法) 04:U 062192a4 ws2_32!WSARecv(Windows Sockets API,用于接收网络数据) 03:U 062191e0 mswsock!WSPRecv(Windows Sockets 2 Service Provider的实现) 02:U 0621917c mswsock!SockWaitForSingleObject(等待网络操作完成) 01:U 06219178 ntdll!NtWaitForSingleObject(Windows内核API,用于等待对象) \`\`\` 请注意,我添加了一些假设的文本(如"OracleDataReader的某个方法")来填补原始堆栈跟踪中未具体说明的部分,并且我省略了与Oracle内部实现相关的许多详细调用。 在这个反转后的堆栈中,我们可以看到: - 调用始于\`OracleDataReader.Read()\`,这是.NET应用程序中用于从Oracle数据库读取数据的常见方法。 - 然后,调用进入\`System.Data.Common.DataAdapter\`的相关方法,这些方法负责将数据从\`OracleDataReader\`读取到\`DataSet\`或\`DataTable\`中。 - 接着,调用通过P/Invoke进入Oracle的非托管客户端库(OCI),并最终到达\`OCIStmtFetch\`,这是用于从Oracle数据库中检索数据的OCI函数。 - 在OCI层之下,是Oracle客户端库的内部实现,这些实现可能涉及网络操作(如\`WSARecv\`)和同步操作(如\`NtWaitForSingleObject\`)。 这种调用顺序是标准的,并且显示了从高级别的.NET API调用到底层系统API和Oracle客户端库的内部实现的过程。 \`NtWaitForSingleObject\` 本身并不直接表示一个网络请求已经发出去了。\`NtWaitForSingleObject\` 是 Windows NT 内核中的一个函数,用于使线程等待一个内核对象的信号。这里的"内核对象"可以是多种类型的对象,比如事件(Event)、互斥体(Mutex)、信号量(Semaphore)、线程(Thread)等。 在网络编程的上下文中,\`NtWaitForSingleObject\` 可能被用来等待一个与网络操作相关的同步对象。例如,在 Windows Sockets (Winsock) 编程中,当进行非阻塞或异步网络操作时,可能会使用事件(Event)或其他同步机制来通知应用程序何时网络操作完成。此时,\`NtWaitForSingleObject\` 可能被用来等待这个事件被触发。 然而,仅仅因为 \`NtWaitForSingleObject\` 被调用,并不意味着网络请求已经发出去了。它可能是在请求已经发出之后,线程在等待网络操作(如发送或接收数据)完成时的某个阶段被调用的。 要确定网络请求是否已经发出,你需要查看更高层次的 API 调用或库函数,这些函数通常负责构建和发送网络请求。例如,在 Winsock 编程中,你可能会看到 \`send\` 或 \`WSASend\` 函数被调用,这些函数实际上负责将数据发送到网络。 因此,如果你看到 \`NtWaitForSingleObject\` 在调用堆栈中,并且你怀疑它与网络请求有关,那么你应该向上查看调用堆栈中的其他函数,特别是那些直接与网络操作相关的函数,以确定请求是否已经发出。同时,你也应该检查是否有任何错误处理代码被执行,以了解在请求发送或等待过程中是否发生了任何错误。 \[NtWaitForSingleObject 函式 (winternl.h) - Win32 apps \| Microsoft Learn\](https://learn.microsoft.com/zh-tw/windows/win32/api/winternl/nf-winternl-ntwaitforsingleobject) NTSTATUS NtWaitForSingleObject( \[in\] HANDLE Handle, \[in\] BOOLEAN Alertable, \[in\] PLARGE_INTEGER Timeout ); \`\`\`bash 0:004\> !help mk SOSEX - Copyright 2007-2015 by Steve Johnson - http://www.stevestechspot.com/ To report bugs or offer feedback about SOSEX, please email sjjohnson@pobox.com mk Usage: !sosex.mk \[-l\] \[-p\] \[-a\] \[-c\] \[-cc\] Produces and displays a merged stack trace of managed and unmanaged frames. Local variables and parameters can be listed by passing -l, -p, or -a -l = Locals -p = Parameters -a = Locals and Parameters -c = Clean (similar to the 'kc' command). Does not show frame numbers, ESP, EIP or source info. -c cannot be used with any other switches. -cc = Same as -c, but also strips namespaces. Provides the most compact stack trace display. \`\`\` \`\`\`bash 0:009\> !mk -p \`\`\` 没有显示非托管的参数。 使用k命令显示前三个参数(不一定准) \[\[原\]调试实战------使用windbg调试DLL卸载时的死锁 - BCN - 博客园 (cnblogs.com)\](https://www.cnblogs.com/bianchengnan/p/12158745.html) \`\`\`bash 0:004\> \~kvn # ChildEBP RetAddr Args to Child 00 062191d8 7254a6c9 0000052c 00000001 00000000 ntdll!NtWaitForSingleObject+0xc 01 062191d8 725530dc 00000002 00000006 46be8804 mswsock!SockWaitForSingleObject+0x139 02 0621924c 75e0385e 000005b8 062192c0 00000001 mswsock!WSPRecv+0x864c 03 0621929c 07601b3b 000005b8 062192c0 00000001 ws2_32!WSARecv+0x11e WARNING: Stack unwind information not available. Following frames may be wrong. 04 062192d8 07a747bd 000005b8 0e76dd4e 00002010 OraOCIEI11!slfipsbs+0xdacf \`\`\` \`\`\`bash 0:004\> !handle 0000052c f Handle 0000052c Type Event Attributes 0 GrantedAccess 0x1f0003: Delete,ReadControl,WriteDac,WriteOwner,Synch QueryState,ModifyState HandleCount 2 PointerCount 65259 Name Object specific information Event Type Manual Reset Event is Waiting \`\`\` 在您提供的调试信息中,\`!handle\` 命令的输出显示了一个事件(Event)句柄的详细信息。这个句柄的编号为 \`0000052c\`,类型为 \`Event\`,并且它的一些关键属性如下: - \*\*Type\*\*: 事件(Event) - \*\*Attributes\*\*: 0(这通常意味着没有特殊的属性被设置,如私有、保护等) - \*\*GrantedAccess\*\*: 0x1f0003,这个权限集包括了删除(Delete)、读取控制(ReadControl)、写入DAC(WriteDac,DAC是Discretionary Access Control的缩写,指自由访问控制列表)、写入所有者(WriteOwner)、同步(Synch)等权限,以及查询状态(QueryState)和修改状态(ModifyState)的权限。 - \*\*HandleCount\*\*: 2,表示这个句柄被两个线程或进程所持有。 - \*\*PointerCount\*\*: 65259,这通常表示有多少个地方(如指针、句柄等)引用了这个事件对象。这个值很高,可能表明这个事件对象在系统中被广泛使用或引用。 - \*\*Name\*\*: \`\`,表示这个事件对象没有与之关联的名称。 \*\*事件对象的具体信息\*\*: - \*\*Event Type\*\*: 手动重置(Manual Reset),这意味着事件必须显式地被重置,而不是在单个等待线程被释放后自动重置。 - \*\*Event is Waiting\*\*: 这表明事件当前处于非信号状态,即没有线程被允许继续执行,因为它们都在等待这个事件被触发(设置为信号状态)。 \*\*分析和影响\*\*: - 由于事件是手动重置的,并且当前处于等待状态,这意味着有线程(可能是多个)正在等待这个事件被触发以继续执行。 - 如果这个事件与某个网络请求相关(尽管从您提供的信息中无法直接确定这一点),那么网络请求可能正在等待这个事件被触发以继续其处理流程。 - 高\`PointerCount\`可能表明这个事件在系统中扮演着重要的角色,被多个组件或线程所依赖。 \*\*调试建议\*\*: - 如果您正在调试与网络请求相关的问题,并且怀疑这个事件与请求的处理有关,您可能需要进一步调查触发这个事件的代码逻辑。 - 使用调试器设置断点,观察哪些线程在等待这个事件,以及哪些线程或操作可能会触发这个事件。 - 检查事件对象的创建和管理逻辑,确保它符合您的预期,并且没有死锁或资源争用的问题。 - 如果可能的话,尝试在不影响系统稳定性的前提下,临时修改事件的属性或行为,以观察它对网络请求处理的影响。但请注意,这种操作需要谨慎进行,并且最好在生产环境的副本或测试环境中进行。 大佬文章:\[记一次 .NET 某拍摄监控软件 卡死分析 - 一线码农 - 博客园 (cnblogs.com)\](https://www.cnblogs.com/huangxincheng/p/17729749.html)
原创
程序卡住记录
本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
评论交流
欢迎留下你的想法