成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

記一次 .NET 某企業OA后端服務 卡死分析

開發 后端
在某個時刻輸出端窗口因為各種原因被他人獨占,導致程序側無法輸出內容到窗口而一直被迫等待,之后朋友將日志輸出切換到文件模式,問題得以解決。

?一、背景

1.講故事

前段時間有位朋友微信找到我,說他生產機器上的 Console 服務看起來像是卡死了,也不生成日志,對方也收不到我的httpclient請求,不知道程序出現什么情況了,特來尋求幫助。

哈哈,一般來說卡死的情況在窗體程序(WinForm,WPF) 上特別多,在 Console,WebApi 中相對較少,既然找到我,那就上 WinDbg 分析吧。

二、WinDbg 分析

1. 程序真的卡死了嗎

程序之所以能跑的梭梭響,全靠線程幫忙,如果玩不轉可能就是線程上出了點什么問題,接下來使用 !t 展示下線程列表。


0:000> !t
ThreadCount: 124
UnstartedThread: 0
BackgroundThread: 105
PendingThread: 0
DeadThread: 18
Hosted Runtime: no
Lock
DBG ID OSID ThreadOBJ State GC Mode GC Alloc Context Domain Count Apt Exception
0 1 65ec 000002097A4BF390 2a020 Preemptive 0000000000000000:0000000000000000 000002097a4bea20 -00001 MTA
3 2 15afc 000002097A50BA10 2b220 Preemptive 00000209060BE8F8:00000209060BEBE8 000002097a4bea20 -00001 MTA (Finalizer)
4 3 11d20 000002097A524EC0 102a220 Preemptive 0000000000000000:0000000000000000 000002097a4bea20 -00001 MTA (Threadpool Worker)
5 9 b8a4 000002097DE10290 3029220 Preemptive 0000000000000000:0000000000000000 000002097a4bea20 -00001 MTA (Threadpool Worker)
6 13 1b22c 000002097DE0ADB0 1029220 Preemptive 0000000000000000:0000000000000000 000002097a4bea20 -00001 MTA (Threadpool Worker)
7 16 1b0e8 000002097DE1A030 202b220 Preemptive 00000209063CB630:00000209063CC1F8 000002097a4bea20 -00001 MTA
8 17 138c8 000002097DE175C0 202b220 Preemptive 00000209063F71C0:00000209063F7BC8 000002097a4bea20 -00001 MTA
9 18 1afd0 000002097DE181E0 202b220 Preemptive 00000209064627E0:0000020906463598 000002097a4bea20 -00001 MTA
10 19 1ac48 000002097DE13310 202b220 Preemptive 000002090632D6C8:000002090632E0D8 000002097a4bea20 -00001 MTA
11 20 18704 000002097DE16390 202b220 Preemptive 00000209063FB5A8:00000209063FBBC8 000002097a4bea20 -00001 MTA
12 21 1ade4 000002097DE187F0 202b220 Preemptive 00000209062EA138:00000209062EA708 000002097a4bea20 -00001 MTA
13 22 13164 000002097DE13920 202b220 Preemptive 0000020906392108:0000020906392A38 000002097a4bea20 -00001 MTA
14 23 1b334 000002097DE169A0 202b220 Preemptive 00000209063CD9E8:00000209063CE1F8 000002097a4bea20 -00001 MTA
...
106 168 19e18 0000020927066770 a029220 Preemptive 0000000000000000:0000000000000000 000002097a4bea20 -00001 MTA (Threadpool Completion Port)
108 136 af74 0000020928590290 8029220 Preemptive 00000209063B60E0:00000209063B6408 000002097a4bea20 -00001 MTA (Threadpool Completion Port)
107 84 e7f0 000002097AD6B600 8029220 Preemptive 00000209063E3300:00000209063E3DD8 000002097a4bea20 -00001 MTA (Threadpool Completion Port)

一般來說卦中的 Lock Count? 列表示當前線程所持有的托管鎖個數,現在顯示的 -00001? 應該是命令不起效果了。。。不過沒關系,我們還可以通過 !syncblk? 來看下 lock 的情況,畢竟 95% 的鎖場景都會用到它。


0:000> !syncblk
Index SyncBlock MonitorHeld Recursion Owning Thread Info SyncBlock Owner
176 000002097E0DA1D8 17 1 00000209216A3500 132c8 71 00000209002c6a68 System.Object
191 000002097E0DAC88 27 1 000002097ADC54F0 1ae90 53 00000209000185e8 System.IO.TextWriter+SyncTextWriter
-----------------------------
Total 270
CCW 0
RCW 0
ComClassFactory 0
Free 32

從卦中的 MonitorHeld=27? 來看,表示這個 SyncTextWriter 對象當前有 13 個線程在等待,有 1 個線程在持有,那這個線程為什么沒有退出呢?接下來可以切到 53 號線程上,查看下它的線程棧。


0:053> ~~[1ae90]s
ntdll!NtWriteFile+0x14:
00007ffd`a70df774 c3 ret
0:053> !clrstack
OS Thread Id: 0x1ae90 (53)
Child SP IP Call Site
00000070505BDE88 00007ffda70df774 [InlinedCallFrame: 00000070505bde88] Interop+Kernel32.WriteFile(IntPtr, Byte*, Int32, Int32 ByRef, IntPtr)
00000070505BDE88 00007ffd32a7cbe2 [InlinedCallFrame: 00000070505bde88] Interop+Kernel32.WriteFile(IntPtr, Byte*, Int32, Int32 ByRef, IntPtr)
00000070505BDE50 00007ffd32a7cbe2 ILStubClass.IL_STUB_PInvoke(IntPtr, Byte*, Int32, Int32 ByRef, IntPtr)
00000070505BDF20 00007ffd3a2d6971 System.ConsolePal+WindowsConsoleStream.WriteFileNative(IntPtr, Byte[], Int32, Int32, Boolean)
00000070505BDF80 00007ffd3a2d672f System.ConsolePal+WindowsConsoleStream.Write(Byte[], Int32, Int32) [/_/src/libraries/System.Console/src/System/ConsolePal.Windows.cs @ 1131]
00000070505BDFD0 00007ffd377c05d9 System.IO.StreamWriter.Flush(Boolean, Boolean) [/_/src/libraries/System.Private.CoreLib/src/System/IO/StreamWriter.cs @ 260]
00000070505BE050 00007ffd3a2d6687 System.IO.StreamWriter.WriteLine(System.String)
00000070505BE0D0 00007ffd3a2d6472 System.IO.TextWriter+SyncTextWriter.WriteLine(System.String) [/_/src/libraries/System.Private.CoreLib/src/System/IO/TextWriter.cs @ 880]
00000070505BE130 00007ffd3a2d640d System.Console.WriteLine(System.String) [/_/src/libraries/System.Console/src/System/Console.cs @ 716]
00000070505BE160 00007ffd3a2375ab HCloud.xxx+d__2.MoveNext()
00000070505BEAE0 00007ffd37e19365 System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[[System.__Canon, System.Private.CoreLib]](System.__Canon ByRef) [/_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs @ 63]
00000070505BEB40 00007ffd3a235cc3 HCloud.xxxx.Execute(Quartz.IJobExecutionContext)
00000070505BEBB0 00007ffd3a231264 Quartz.xxx+d__9.MoveNext()
00000070505BEE90 00007ffd3a230183 System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[[Quartz.Core.JobRunShell+d__9, Quartz]](d__9 ByRef) [/_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs @ 63]
00000070505BEF10 00007ffd3a2300db System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Start[[Quartz.Core.JobRunShell+d__9, Quartz]](d__9 ByRef) [/_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncTaskMethodBuilder.cs @ 33]
00000070505BEF40 00007ffd3a230082 Quartz.xxxxl.Run(System.Threading.CancellationToken)
00000070505BF020 00007ffd3a22ffc3 Quartz.Core.QuartzSchedulerThread+c__DisplayClass28_0.b__0()
00000070505BF060 00007ffd3939b71a System.Threading.Tasks.Task`1[[System.__Canon, System.Private.CoreLib]].InnerInvoke() [/_/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/Future.cs @ 507]
00000070505BF0C0 00007ffd37d54431 System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(System.Threading.Thread, System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object) [/_/src/libraries/System.Private.CoreLib/src/System/Threading/ExecutionContext.cs @ 300]
00000070505BF110 00007ffd37d53657 System.Threading.Tasks.Task.ExecuteWithThreadLocal(System.Threading.Tasks.Task ByRef, System.Threading.Thread) [/_/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/Task.cs @ 2352]
00000070505BF1C0 00007ffd37d50e04 System.Threading.ThreadPoolWorkQueue.Dispatch() [/_/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadPool.cs @ 677]
00000070505BF690 00007ffd925ea7a3 [DebuggerU2MCatchHandlerFrame: 00000070505bf690]

仔細觀察線程棧會很驚訝的發現,居然還能卡在 System.Console.WriteLine? 方法上,挺奇怪的,為了探究原因,我們使用 k 命令看下非托管棧。


0:053> k 5
# Child-SP RetAddr Call Site
00 00000070`505bddd8 00007ffd`a32febda ntdll!NtWriteFile+0x14
01 00000070`505bdde0 00007ffd`32a7cbe2 KERNELBASE!WriteFile+0x7a
02 00000070`505bde50 00007ffd`3a2d6971 0x00007ffd`32a7cbe2
03 00000070`505bdf20 00007ffd`3a2d672f System_Console!System.ConsolePal.WindowsConsoleStream.WriteFileNative+0x61
04 00000070`505bdf80 00007ffd`377c05d9 System_Console!System.ConsolePal.WindowsConsoleStream.Write+0x3f

0:053> ub ntdll!NtWriteFile+0x14
ntdll!NtDeviceIoControlFile+0x15:
00007ffd`a70df755 cd2e int 2Eh
00007ffd`a70df757 c3 ret
00007ffd`a70df758 0f1f840000000000 nop dword ptr [rax+rax]
ntdll!NtWriteFile:
00007ffd`a70df760 4c8bd1 mov r10,rcx
00007ffd`a70df763 b808000000 mov eax,8
00007ffd`a70df768 f604250803fe7f01 test byte ptr [SharedUserData+0x308 (00000000`7ffe0308)],1
00007ffd`a70df770 7503 jne ntdll!NtWriteFile+0x15 (00007ffd`a70df775)
00007ffd`a70df772 0f05 syscall

從上面的 syscall? 系統調用關鍵詞看,代碼是將用戶態的 ntdll!NtWriteFile? 切到入了內核態的 nt!NtWriteFile 方法,那進入了內核態為什么沒有返回呢?這又是一個值得思索的問題。

2. 為什么進入了內核態無返回

其實 ntdll!NtWriteFile 這個 win32 api 方法的第一個參數是一個 handle 的文件句柄,簽名如下。


__kernel_entry NTSYSCALLAPI NTSTATUS NtWriteFile(
[in] HANDLE FileHandle,
[in, optional] HANDLE Event,
[in, optional] PIO_APC_ROUTINE ApcRoutine,
[in, optional] PVOID ApcContext,
[out] PIO_STATUS_BLOCK IoStatusBlock,
[in] PVOID Buffer,
[in] ULONG Length,
[in, optional] PLARGE_INTEGER ByteOffset,
[in, optional] PULONG Key
);

可能 handle 在內核中被別人占用了,可以用 !handle? 查看下 rcx 寄存器。


0:053> r
rax=0000000000000008 rbx=00000070505bdf50 rcx=0000000000000418
rdx=0000000000000000 rsi=0000000000000000 rdi=0000000000000418
rip=00007ffda70df774 rsp=00000070505bddd8 rbp=00000070505bdf10
r8=0000000002000805 r9=0000000000000000 r10=0000020906191620
r11=00000070505bc8f8 r12=0000000000000100 r13=0000000000000053
r14=0000000000000077 r15=000002097adc54f0
iopl=0 nv up ei pl zr na po nc
cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
ntdll!NtWriteFile+0x14:
00007ffd`a70df774 c3 ret
0:053> !handle 0000000000000418 f
Handle 0000000000000418
Type File
Attributes 0
GrantedAccess 0x120196:
ReadControl,Synch
Write/Add,Append/SubDir/CreatePipe,WriteEA,ReadAttr,WriteAttr
HandleCount 3
PointerCount 65483
No object specific information available

哈哈,其實也看不出什么,也沒法進入內核態,所以下一步只能到網上搜搜看,其實有經驗的朋友肯定猜出來了,應該是控制臺啟用了 快捷編輯窗口 ,截圖如下:

圖片

快捷編輯窗口? 簡而言之就是用戶可以在控制臺上獨占這個窗口,編輯一些內容, 可一旦被用戶獨占,那程序側就沒法輸出內容到 控制臺窗口? 上了,只能在 內核態 傻傻等等,這應該就是形成原因,畫個圖大概就像下面這樣。

圖片

將信息告訴朋友后,朋友說他用的是 Windows 服務部署,但不管是什么模式部署,注釋掉 Console.WriteLine 肯定沒錯。

三:總結

這次卡死的事故,主要還是開發人員大量的使用 Console.WriteLine 來輸出日志,在某個時刻輸出端窗口因為各種原因被他人獨占,導致程序側無法輸出內容到窗口而一直被迫等待,之后朋友將日志輸出切換到文件模式,問題得以解決。

其實這個問題很多新手朋友都會犯,特此記錄下來。

責任編輯:武曉燕 來源: 一線碼農聊技術
相關推薦

2024-05-20 09:39:02

.NETurl線程池

2023-09-27 07:23:10

.NET監控軟件

2023-05-15 11:15:50

.NET門診語句

2024-09-14 10:28:56

.NET卡死程序

2024-07-01 13:00:24

.NET網絡邊緣計算

2024-11-29 10:06:59

2022-01-17 21:28:36

管理系統.NET

2023-06-26 00:12:46

2023-03-26 20:24:50

ERP網站系統

2024-05-28 10:18:30

WPF程序數據

2024-06-06 10:51:15

自動化系統推測

2024-12-27 13:31:18

.NETdump調試

2023-04-06 10:52:18

2024-03-28 12:56:36

2024-07-12 11:20:34

.NET崩潰視覺程序

2023-07-06 10:11:38

.NET模式dump

2024-03-26 00:44:53

.NETCIM系統

2021-10-27 07:30:32

.NETCPU論壇

2023-10-07 13:28:53

.NET軟件賬本

2024-05-31 12:56:06

.NET代碼方法
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲视频在线免费观看 | 免费网站国产 | 欧美日韩免费 | 成人免费网站www网站高清 | 国产乱精品一区二区三区 | 国产偷久久一级精品60部 | 国产一区二区三区免费观看视频 | 欧美性大战久久久久久久蜜臀 | 涩涩视频在线观看 | 国产精品高清一区二区三区 | 九九精品网 | 国产成人精品午夜 | 伦理午夜电影免费观看 | 日韩在线精品视频 | 亚洲精品久久久久久国产精华液 | 9999久久| 婷婷在线视频 | 六月色婷| 91精品国产综合久久福利软件 | 成人免费视频网站在线观看 | 国产性色视频 | 精品国产欧美一区二区三区成人 | 国产粉嫩尤物极品99综合精品 | 久久一区二区三区四区 | 日韩三级一区 | 国产精品美女久久久久久免费 | 国产精品久久久久久久久久久免费看 | 天天爽天天干 | 日韩欧美精品一区 | 国产视频久久 | 精品久久影院 | 中文字幕一页二页 | 日本国产精品视频 | 亚洲成人一区二区三区 | 国产农村妇女精品一区 | 婷婷色婷婷 | 欧美久久久久 | 久久99精品久久久久 | 亚洲a级| 特级黄一级播放 | 国产激情在线 |