Eğitim
Öğrenme yolu
C# konsol uygulamalarında hata ayıklama (C#, Bölüm 6 ile çalışmaya başlama) - Training
C# konsol uygulamalarında hata ayıklama (C#, Bölüm 6 ile çalışmaya başlama)
Bu tarayıcı artık desteklenmiyor.
En son özelliklerden, güvenlik güncelleştirmelerinden ve teknik destekten faydalanmak için Microsoft Edge’e yükseltin.
Bu makale şunlar için geçerlidir: ✔️ .NET Core 3.1 SDK ve sonraki sürümler
Bu öğreticide kilitlenme senaryosunda hata ayıklamayı öğreneceksiniz. Sağlanan örnek ASP.NET Core web uygulaması kaynak kodu deposunu kullanarak kasıtlı olarak kilitlenmeye neden olabilirsiniz. Uç nokta yanıt vermeyi durdurur ve iş parçacığı birikmesi yaşar. Sorunu analiz etmek için temel dökümler, çekirdek döküm analizi ve işlem izleme gibi çeşitli araçları nasıl kullanabileceğinizi öğreneceksiniz.
Bu öğreticide şunları yapacaksınız:
Öğretici şunları kullanır:
Uygulama yanıt vermeme durumunu araştırmak için çekirdek dökümü veya bellek dökümü, iş parçacıklarının durumunu ve çekişme sorunları olabilecek olası kilitleri incelemenize olanak tanır. Örnek kök dizinden aşağıdaki komutu kullanarak örnek hata ayıklama uygulamasını çalıştırın:
dotnet run
İşlem kimliğini bulmak için aşağıdaki komutu kullanın:
dotnet-trace ps
Komut çıkışınızdaki işlem kimliğini not alın. İşlem kimliğimiz şeklindeydi 4807
, ancak sizinki farklı olacaktır. Örnek sitede bir API uç noktası olan aşağıdaki URL'ye gidin:
https://localhost:5001/api/diagscenario/deadlock
Siteye yapılan API isteği yanıt vermeyi durdurur. İsteğin yaklaşık 10-15 saniye çalışmasına izin verin. Ardından aşağıdaki komutu kullanarak çekirdek dökümünü oluşturun:
Çekirdek döküm analizini başlatmak için aşağıdaki dotnet-dump analyze
komutu kullanarak çekirdek dökümünü açın. bağımsız değişkeni, daha önce toplanan çekirdek döküm dosyasının yoludur.
dotnet-dump analyze ~/.dotnet/tools/core_20190513_143916
Yanıt vermeyebiliyor olabilecek bir uygulamaya baktığınızda işlemdeki iş parçacığı etkinliği için genel bir his istiyorsunuz. Aşağıda gösterildiği gibi komutunu kullanabilirsiniz threads
:
> threads
*0 0x1DBFF (121855)
1 0x1DC01 (121857)
2 0x1DC02 (121858)
3 0x1DC03 (121859)
4 0x1DC04 (121860)
5 0x1DC05 (121861)
6 0x1DC06 (121862)
7 0x1DC07 (121863)
8 0x1DC08 (121864)
9 0x1DC09 (121865)
10 0x1DC0A (121866)
11 0x1DC0D (121869)
12 0x1DC0E (121870)
13 0x1DC10 (121872)
14 0x1DC11 (121873)
15 0x1DC12 (121874)
16 0x1DC13 (121875)
17 0x1DC14 (121876)
18 0x1DC15 (121877)
19 0x1DC1C (121884)
20 0x1DC1D (121885)
21 0x1DC1E (121886)
22 0x1DC21 (121889)
23 0x1DC22 (121890)
24 0x1DC23 (121891)
25 0x1DC24 (121892)
26 0x1DC25 (121893)
...
...
317 0x1DD48 (122184)
318 0x1DD49 (122185)
319 0x1DD4A (122186)
320 0x1DD4B (122187)
321 0x1DD4C (122188)
Çıkış, o anda işlemde çalışmakta olan tüm iş parçacıklarını ilişkili hata ayıklayıcı iş parçacığı kimliği ve işletim sistemi iş parçacığı kimliğiyle gösterir. Çıktıya göre 300'den fazla iş parçacığı vardır.
Sonraki adım, her iş parçacığının çağrı yığınını alarak iş parçacıklarının şu anda ne yaptığını daha iyi anlamaktır. clrstack
komutu çağrı yığınlarının çıkışını almak için kullanılabilir. Tek bir çağrı yığını veya tüm çağrı yığınlarının çıkışını alabilir. İşlemdeki tüm iş parçacıklarının tüm çağrı yığınlarının çıkışını almak için aşağıdaki komutu kullanın:
clrstack -all
Çıkışın temsili bir kısmı şöyle görünür:
...
...
...
Child SP IP Call Site
00007F2AE37B5680 00007f305abc6360 [GCFrame: 00007f2ae37b5680]
00007F2AE37B5770 00007f305abc6360 [GCFrame: 00007f2ae37b5770]
00007F2AE37B57D0 00007f305abc6360 [HelperMethodFrame_1OBJ: 00007f2ae37b57d0] System.Threading.Monitor.ReliableEnter(System.Object, Boolean ByRef)
00007F2AE37B5920 00007F2FE392B31F testwebapi.Controllers.DiagScenarioController.<deadlock>b__3_1() [/home/marioh/webapi/Controllers/diagscenario.cs @ 36]
00007F2AE37B5950 00007F2FE392B46D System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object) [/__w/3/s/src/System.Private.CoreLib/shared/System/Threading/ExecutionContext.cs @ 201]
00007F2AE37B5CA0 00007f30593044af [GCFrame: 00007f2ae37b5ca0]
00007F2AE37B5D70 00007f30593044af [DebuggerU2MCatchHandlerFrame: 00007f2ae37b5d70]
OS Thread Id: 0x1dc82
Child SP IP Call Site
00007F2AE2FB4680 00007f305abc6360 [GCFrame: 00007f2ae2fb4680]
00007F2AE2FB4770 00007f305abc6360 [GCFrame: 00007f2ae2fb4770]
00007F2AE2FB47D0 00007f305abc6360 [HelperMethodFrame_1OBJ: 00007f2ae2fb47d0] System.Threading.Monitor.ReliableEnter(System.Object, Boolean ByRef)
00007F2AE2FB4920 00007F2FE392B31F testwebapi.Controllers.DiagScenarioController.<deadlock>b__3_1() [/home/marioh/webapi/Controllers/diagscenario.cs @ 36]
00007F2AE2FB4950 00007F2FE392B46D System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object) [/__w/3/s/src/System.Private.CoreLib/shared/System/Threading/ExecutionContext.cs @ 201]
00007F2AE2FB4CA0 00007f30593044af [GCFrame: 00007f2ae2fb4ca0]
00007F2AE2FB4D70 00007f30593044af [DebuggerU2MCatchHandlerFrame: 00007f2ae2fb4d70]
OS Thread Id: 0x1dc83
Child SP IP Call Site
00007F2AE27B3680 00007f305abc6360 [GCFrame: 00007f2ae27b3680]
00007F2AE27B3770 00007f305abc6360 [GCFrame: 00007f2ae27b3770]
00007F2AE27B37D0 00007f305abc6360 [HelperMethodFrame_1OBJ: 00007f2ae27b37d0] System.Threading.Monitor.ReliableEnter(System.Object, Boolean ByRef)
00007F2AE27B3920 00007F2FE392B31F testwebapi.Controllers.DiagScenarioController.<deadlock>b__3_1() [/home/marioh/webapi/Controllers/diagscenario.cs @ 36]
00007F2AE27B3950 00007F2FE392B46D System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object) [/__w/3/s/src/System.Private.CoreLib/shared/System/Threading/ExecutionContext.cs @ 201]
00007F2AE27B3CA0 00007f30593044af [GCFrame: 00007f2ae27b3ca0]
00007F2AE27B3D70 00007f30593044af [DebuggerU2MCatchHandlerFrame: 00007f2ae27b3d70]
OS Thread Id: 0x1dc84
Child SP IP Call Site
00007F2AE1FB2680 00007f305abc6360 [GCFrame: 00007f2ae1fb2680]
00007F2AE1FB2770 00007f305abc6360 [GCFrame: 00007f2ae1fb2770]
00007F2AE1FB27D0 00007f305abc6360 [HelperMethodFrame_1OBJ: 00007f2ae1fb27d0] System.Threading.Monitor.ReliableEnter(System.Object, Boolean ByRef)
00007F2AE1FB2920 00007F2FE392B31F testwebapi.Controllers.DiagScenarioController.<deadlock>b__3_1() [/home/marioh/webapi/Controllers/diagscenario.cs @ 36]
00007F2AE1FB2950 00007F2FE392B46D System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object) [/__w/3/s/src/System.Private.CoreLib/shared/System/Threading/ExecutionContext.cs @ 201]
00007F2AE1FB2CA0 00007f30593044af [GCFrame: 00007f2ae1fb2ca0]
00007F2AE1FB2D70 00007f30593044af [DebuggerU2MCatchHandlerFrame: 00007f2ae1fb2d70]
OS Thread Id: 0x1dc85
Child SP IP Call Site
00007F2AE17B1680 00007f305abc6360 [GCFrame: 00007f2ae17b1680]
00007F2AE17B1770 00007f305abc6360 [GCFrame: 00007f2ae17b1770]
00007F2AE17B17D0 00007f305abc6360 [HelperMethodFrame_1OBJ: 00007f2ae17b17d0] System.Threading.Monitor.ReliableEnter(System.Object, Boolean ByRef)
00007F2AE17B1920 00007F2FE392B31F testwebapi.Controllers.DiagScenarioController.<deadlock>b__3_1() [/home/marioh/webapi/Controllers/diagscenario.cs @ 36]
00007F2AE17B1950 00007F2FE392B46D System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object) [/__w/3/s/src/System.Private.CoreLib/shared/System/Threading/ExecutionContext.cs @ 201]
00007F2AE17B1CA0 00007f30593044af [GCFrame: 00007f2ae17b1ca0]
00007F2AE17B1D70 00007f30593044af [DebuggerU2MCatchHandlerFrame: 00007f2ae17b1d70]
OS Thread Id: 0x1dc86
Child SP IP Call Site
00007F2AE0FB0680 00007f305abc6360 [GCFrame: 00007f2ae0fb0680]
00007F2AE0FB0770 00007f305abc6360 [GCFrame: 00007f2ae0fb0770]
00007F2AE0FB07D0 00007f305abc6360 [HelperMethodFrame_1OBJ: 00007f2ae0fb07d0] System.Threading.Monitor.ReliableEnter(System.Object, Boolean ByRef)
00007F2AE0FB0920 00007F2FE392B31F testwebapi.Controllers.DiagScenarioController.<deadlock>b__3_1() [/home/marioh/webapi/Controllers/diagscenario.cs @ 36]
00007F2AE0FB0950 00007F2FE392B46D System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object) [/__w/3/s/src/System.Private.CoreLib/shared/System/Threading/ExecutionContext.cs @ 201]
00007F2AE0FB0CA0 00007f30593044af [GCFrame: 00007f2ae0fb0ca0]
00007F2AE0FB0D70 00007f30593044af [DebuggerU2MCatchHandlerFrame: 00007f2ae0fb0d70]
OS Thread Id: 0x1dc87
Child SP IP Call Site
00007F2AE07AF680 00007f305abc6360 [GCFrame: 00007f2ae07af680]
00007F2AE07AF770 00007f305abc6360 [GCFrame: 00007f2ae07af770]
00007F2AE07AF7D0 00007f305abc6360 [HelperMethodFrame_1OBJ: 00007f2ae07af7d0] System.Threading.Monitor.ReliableEnter(System.Object, Boolean ByRef)
00007F2AE07AF920 00007F2FE392B31F testwebapi.Controllers.DiagScenarioController.<deadlock>b__3_1() [/home/marioh/webapi/Controllers/diagscenario.cs @ 36]
00007F2AE07AF950 00007F2FE392B46D System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object) [/__w/3/s/src/System.Private.CoreLib/shared/System/Threading/ExecutionContext.cs @ 201]
00007F2AE07AFCA0 00007f30593044af [GCFrame: 00007f2ae07afca0]
00007F2AE07AFD70 00007f30593044af [DebuggerU2MCatchHandlerFrame: 00007f2ae07afd70]
OS Thread Id: 0x1dc88
Child SP IP Call Site
00007F2ADFFAE680 00007f305abc6360 [GCFrame: 00007f2adffae680]
00007F2ADFFAE770 00007f305abc6360 [GCFrame: 00007f2adffae770]
00007F2ADFFAE7D0 00007f305abc6360 [HelperMethodFrame_1OBJ: 00007f2adffae7d0] System.Threading.Monitor.ReliableEnter(System.Object, Boolean ByRef)
00007F2ADFFAE920 00007F2FE392B31F testwebapi.Controllers.DiagScenarioController.<deadlock>b__3_1() [/home/marioh/webapi/Controllers/diagscenario.cs @ 36]
00007F2ADFFAE950 00007F2FE392B46D System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object) [/__w/3/s/src/System.Private.CoreLib/shared/System/Threading/ExecutionContext.cs @ 201]
00007F2ADFFAECA0 00007f30593044af [GCFrame: 00007f2adffaeca0]
00007F2ADFFAED70 00007f30593044af [DebuggerU2MCatchHandlerFrame: 00007f2adffaed70]
...
...
300'den fazla iş parçacığı için çağrı yığınını gözlemlemek, iş parçacıklarının çoğunluğunun ortak bir çağrı yığınını paylaştığı bir desen gösterir:
OS Thread Id: 0x1dc88
Child SP IP Call Site
00007F2ADFFAE680 00007f305abc6360 [GCFrame: 00007f2adffae680]
00007F2ADFFAE770 00007f305abc6360 [GCFrame: 00007f2adffae770]
00007F2ADFFAE7D0 00007f305abc6360 [HelperMethodFrame_1OBJ: 00007f2adffae7d0] System.Threading.Monitor.ReliableEnter(System.Object, Boolean ByRef)
00007F2ADFFAE920 00007F2FE392B31F testwebapi.Controllers.DiagScenarioController.<deadlock>b__3_1() [/home/marioh/webapi/Controllers/diagscenario.cs @ 36]
00007F2ADFFAE950 00007F2FE392B46D System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object) [/__w/3/s/src/System.Private.CoreLib/shared/System/Threading/ExecutionContext.cs @ 201]
00007F2ADFFAECA0 00007f30593044af [GCFrame: 00007f2adffaeca0]
00007F2ADFFAED70 00007f30593044af [DebuggerU2MCatchHandlerFrame: 00007f2adffaed70]
Çağrı yığını isteğin kilitlenme yöntemimize ulaştığını gösteriyor ve bu da çağrısı Monitor.ReliableEnter
yapıyor. Bu yöntem, iş parçacıklarının bir monitör kilidi girmeye çalıştığını gösterir. Kilidin kullanılabilirliğini bekliyorlar. Büyük olasılıkla farklı bir iş parçacığı tarafından kilitlenmiştir.
Ardından bir sonraki adım, monitör kilidini tutan iş parçacığını bulmaktır. İzleyiciler genellikle kilit bilgilerini eşitleme bloğu tablosunda depoladığından, daha fazla bilgi almak için komutunu kullanabiliriz syncblk
:
> syncblk
Index SyncBlock MonitorHeld Recursion Owning Thread Info SyncBlock Owner
43 00000246E51268B8 603 1 0000024B713F4E30 5634 28 00000249654b14c0 System.Object
44 00000246E5126908 3 1 0000024B713F47E0 51d4 29 00000249654b14d8 System.Object
-----------------------------
Total 344
CCW 1
RCW 2
ComClassFactory 0
Free 0
İki ilginç sütun MonitorHeld ve Sahip Olan İş Parçacığı Bilgileri'dir. MonitorHeld sütunu, bir izleyici kilidinin bir iş parçacığı tarafından alınıp alınmadığını ve bekleyen iş parçacıklarının sayısını gösterir. Sahip Olan İş Parçacığı Bilgileri sütunu, monitör kilidinin şu anda hangi iş parçacığına sahip olduğunu gösterir. İş parçacığı bilgilerinin üç farklı alt toplamı vardır. İkinci alt sütun işletim sistemi iş parçacığı kimliğini gösterir.
Bu noktada, iki farklı iş parçacığının (0x5634 ve 0x51d4) bir monitör kilidi tuttuğunu biliyoruz. Sonraki adım, bu iş parçacıklarının neler yaptığına göz atmaktır. Kilidi tutarken süresiz olarak takılıp takılmadıklarını kontrol etmeliyiz. Şimdi iş parçacıklarının setthread
her birine geçmek ve çağrı yığınlarını görüntülemek için ve clrstack
komutlarını kullanalım.
İlk iş parçacığına bakmak için komutunu çalıştırın setthread
ve 0x5634 iş parçacığının dizinini bulun (dizinimiz 28 idi). Kilitlenme işlevi bir kilit almak için bekliyor, ancak kilidin sahibi zaten o. Kilit içinde, zaten tuttuğu kilidi bekliyor.
> setthread 28
> clrstack
OS Thread Id: 0x5634 (28)
Child SP IP Call Site
0000004E46AFEAA8 00007fff43a5cbc4 [GCFrame: 0000004e46afeaa8]
0000004E46AFEC18 00007fff43a5cbc4 [GCFrame: 0000004e46afec18]
0000004E46AFEC68 00007fff43a5cbc4 [HelperMethodFrame_1OBJ: 0000004e46afec68] System.Threading.Monitor.Enter(System.Object)
0000004E46AFEDC0 00007FFE5EAF9C80 testwebapi.Controllers.DiagScenarioController.DeadlockFunc() [C:\Users\dapine\Downloads\Diagnostic_scenarios_sample_debug_target\Controllers\DiagnosticScenarios.cs @ 58]
0000004E46AFEE30 00007FFE5EAF9B8C testwebapi.Controllers.DiagScenarioController.<deadlock>b__3_0() [C:\Users\dapine\Downloads\Diagnostic_scenarios_sample_debug_target\Controllers\DiagnosticScenarios.cs @ 26]
0000004E46AFEE80 00007FFEBB251A5B System.Threading.ThreadHelper.ThreadStart_Context(System.Object) [/_/src/System.Private.CoreLib/src/System/Threading/Thread.CoreCLR.cs @ 44]
0000004E46AFEEB0 00007FFE5EAEEEEC System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object) [/_/src/System.Private.CoreLib/shared/System/Threading/ExecutionContext.cs @ 201]
0000004E46AFEF20 00007FFEBB234EAB System.Threading.ThreadHelper.ThreadStart() [/_/src/System.Private.CoreLib/src/System/Threading/Thread.CoreCLR.cs @ 93]
0000004E46AFF138 00007ffebdcc6b63 [GCFrame: 0000004e46aff138]
0000004E46AFF3A0 00007ffebdcc6b63 [DebuggerU2MCatchHandlerFrame: 0000004e46aff3a0]
İkinci iş parçacığı benzerdir. Ayrıca zaten sahip olduğu bir kilidi almaya çalışıyor. Bekleyen kalan 300'ün üzerinde iş parçacığı da kilitlenmeye neden olan kilitlerden birini bekliyor olabilir.
.NET geri bildirimi
.NET, açık kaynak bir projedir. Geri bildirim sağlamak için bir bağlantı seçin:
Eğitim
Öğrenme yolu
C# konsol uygulamalarında hata ayıklama (C#, Bölüm 6 ile çalışmaya başlama) - Training
C# konsol uygulamalarında hata ayıklama (C#, Bölüm 6 ile çalışmaya başlama)
Belgeler
Yüksek CPU kullanımında hata ayıklama - .NET Core - .NET
.NET Core'da yüksek CPU kullanımında hata ayıklama işleminde size yol gösteren bir öğretici.
dotnet-dump tanılama aracı - .NET CLI - .NET
Yerel hata ayıklayıcı olmadan Windows ve Linux dökümlerini toplamak ve analiz etmek için dotnet-dump CLI aracını yüklemeyi ve kullanmayı öğrenin.
Bellek sızıntısında hata ayıklama öğreticisi - .NET
.NET'te bellek sızıntısında hata ayıklamayı öğrenin.