偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

記一次 .NET 某CRM物流行業(yè)管理系統(tǒng)崩潰分析

開發(fā) 前端
如果調用線程執(zhí)行了錯誤的?_nativeAssemblyLoadContext,那最多就是拋個異常,不會導致程序崩潰,相反如果讓終結器線程崩潰了,那就是大大的一個災難。無法挽回。

一、背景

1. 講故事

微信上有位朋友找到我,說他們部署在linux上的 .net 程序會隔幾天崩潰一次,一直找不到原因,讓我?guī)兔聪略趺椿厥?,讓朋友?procdump 抓了一個dump下來,然后就是正式的分析啦。

二、崩潰分析

1. 為什么會崩潰

拿到dump之后,雙擊dump打開,會看到程序崩潰的原因,參考如下:

(1.d): Signal SIGSEGV (Segmentation fault) code SEGV_MAPERR (Address not mapped to object) at 0x108

libc_so!wait4+0x57:
00007f44`37aa5c17 483d00f0ffff    cmp     rax,0FFFFFFFFFFFFF000h

從卦中可以看到如下幾點信息:

  • d 表示 d 號線程出現(xiàn)了崩潰。
  • SIGSEGV 表示經(jīng)典的 段錯誤,用 Windows 的話術就是訪問違例。
  • SEGV_MAPERR 表示mapper錯誤,即當前地址無法映射到有效內存。
  • 0x108 當前訪問的地址。

既然都說到 d 號線程了,接下來就是切過去看看,參考輸出如下:

0:007> ~~[d]s
libc_so!wait4+0x57:
00007f44`37aa5c17 483d00f0ffff    cmp     rax,0FFFFFFFFFFFFF000h
0:007> k
# Child-SP          RetAddr               Call Site
0000007f44`367d1cd0 00007f44`37851c05     libc_so!wait4+0x57
0100007f44`367d1d00 00007f44`37852b40     libcoreclr!PROCCreateCrashDump+0x275 [/__w/1/s/src/coreclr/pal/src/thread/process.cpp @ 2307] 
0200007f44`367d1d60 00007f44`3782518e     libcoreclr!PROCCreateCrashDumpIfEnabled+0x770 [/__w/1/s/src/coreclr/pal/src/thread/process.cpp @ 2524] 
0300007f44`367d1df0 00007f44`37824765     libcoreclr!invoke_previous_action+0x10e [/__w/1/s/src/coreclr/pal/src/exception/signal.cpp @ 397] 
0400007f44`367d1e30 00007f44`37a0e050     libcoreclr!sigsegv_handler+0x1d5 [/__w/1/s/src/coreclr/pal/src/exception/signal.cpp @ 631] 
0500007f44`367d2ac0 00007f44`37754e2a     libc_so!_sigaction+0x40
0600007f44`368d2830 00007f44`375109c3     libcoreclr!CustomAssemblyBinder::PrepareForLoadContextRelease+0xa [/__w/1/s/src/coreclr/binder/customassemblybinder.cpp @ 222] 
0700007f44`368d2850 00007f44`1adbe9c5     libcoreclr!AssemblyNative_PrepareForAssemblyLoadContextRelease+0x93 [/__w/1/s/src/coreclr/inc/clrtypes.h @ 1263] 
0800007f44`368d28e0 00007f44`224242cd     System_Private_CoreLib!System.Runtime.Loader.AssemblyLoadContext.InitiateUnload+0xe5 [/_/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs @ 151] 
0900007f44`368d29b0 00007f44`376de496     System_Private_CoreLib!System.Runtime.Loader.AssemblyLoadContext.Finalize+0x2d [/_/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs @ 124] 
0a 00007f44`368d29d0 00007f44`3749b8a3     libcoreclr!FastCallFinalizeWorker+0x6 [/__w/1/s/src/coreclr/vm/amd64/calldescrworkeramd64.S @ 31] 
0b (Inline Function) --------`--------     libcoreclr!FastCallFinalize+0x4a [/__w/1/s/src/coreclr/vm/methodtable.cpp @ 4771] 
0c 00007f44`368d29e0 00007f44`375540f5     libcoreclr!MethodTable::CallFinalizer+0x253 [/__w/1/s/src/coreclr/vm/spinlock.h @ 4889] 
0d (Inline Function) --------`--------     libcoreclr!CallFinalizer+0x58 [/__w/1/s/src/coreclr/vm/finalizerthread.cpp @ 75] 
0e 00007f44`368d2a40 00007f44`37554345     libcoreclr!FinalizerThread::FinalizeAllObjects+0xc5 [/__w/1/s/src/coreclr/inc/volatile.h @ 104] 
0f00007f44`368d2a80 00007f44`374e5b75     libcoreclr!FinalizerThread::FinalizerThreadWorker+0x95 [/__w/1/s/src/coreclr/inc/volatile.h @ 354] 
10 (Inline Function) --------`--------     libcoreclr!ManagedThreadBase_DispatchInner+0x2 [/__w/1/s/src/coreclr/vm/threads.cpp @ 7222] 
11 (Inline Function) --------`--------     libcoreclr!ManagedThreadBase_DispatchMiddle+0x3d [/__w/1/s/src/coreclr/vm/util.hpp @ 7266] 
12 (Inline Function) --------`--------     libcoreclr!<unnamed-class>::operator()+0x3d [/__w/1/s/src/coreclr/vm/util.hpp @ 7424] 
13 (InlineFunction) --------`--------     libcoreclr!<unnamed-class>::operator()+0xa9 [/__w/1/s/src/coreclr/vm/util.hpp @ 7426] 
14 00007f44`368d2cd0 00007f44`374e619d     libcoreclr!ManagedThreadBase_DispatchOuter+0x135 [/__w/1/s/src/coreclr/vm/util.hpp @ 7450] 
15 (InlineFunction) --------`--------     libcoreclr!ManagedThreadBase_NoADTransition+0x18 [/__w/1/s/src/coreclr/vm/threads.cpp @ 7494] 
16 00007f44`368d2de0 00007f44`375545e8     libcoreclr!ManagedThreadBase::FinalizerBase+0x2d [/__w/1/s/src/coreclr/vm/threads.cpp @ 7514] 
17 00007f44`368d2e10 00007f44`3785476e     libcoreclr!FinalizerThread::FinalizerThreadStart+0x58 [/__w/1/s/src/coreclr/vm/finalizerthread.cpp @ 403] 
18 00007f44`368d2e30 00007f44`37a5b1f5     libcoreclr!CorUnix::CPalThread::ThreadEntry+0x1fe [/__w/1/s/src/coreclr/pal/inc/pal.h @ 1763] 
19 00007f44`368d2ee0 00007f44`37adab00     libc_so!pthread_condattr_setpshared+0x515
1a 00007f44`368d2f80ffffffff`ffffffff     libc_so!_clone+0x40
1b 00007f44`368d2f88 00000000`00000000     0xffffffff`ffffffff

從卦象看是終結器線程正在調用 AssemblyLoadContext 的析構函數(shù),在coreclr層的 PrepareForLoadContextRelease 函數(shù)中拋出了訪問違例,這段代碼很明顯犯了編程的一個大忌,即不手工調用Dispose,而是依賴終結器線程的兜底,導致災難的發(fā)生,

不過按理說這些代碼都是固若金湯,拋異常也是有點奇葩。。。

2. 為什么會拋出異常

要想找到這個答案,可以借助可視化的VS面板,將 dump 拖到 VS 中,在線程面板中找到 終結器線程,然后觀察 InitiateUnload 方法的代碼邏輯,可以清楚的看到然來是 _nativeAssemblyLoadContext 字段為 null 導致的,截圖如下:

圖片圖片

觀察源代碼發(fā)現(xiàn) _nativeAssemblyLoadContext 是 coreclr 對外提供操作的句柄,它的賦值是在 AssemblyLoadContext 初始化構造時,截圖如下:

圖片圖片

說實話看到這個源頭就蒙圈了,_nativeAssemblyLoadContext 居然還有null的情況,這也就說明 InitializeAssemblyLoadContext 函數(shù)有為null的情況,簽名如下:

[DllImport("QCall", CharSet = CharSet.Unicode)]
 private static extern IntPtr InitializeAssemblyLoadContext(IntPtr ptrAssemblyLoadContext, bool fRepresentsTPALoadContext, bool isCollectible);

3. 接下來怎么辦

針對 _nativeAssemblyLoadCnotallow=null 這種奇葩情況,我個人提供兩種方案。

1) 使用 using 替代 兜底線程

如果調用線程執(zhí)行了錯誤的 _nativeAssemblyLoadContext,那最多就是拋個異常,不會導致程序崩潰,相反如果讓終結器線程崩潰了,那就是大大的一個災難。無法挽回。

2) 使用 harmony 跟蹤

如果你是一個極客,一定要抓到 _nativeAssemblyLoadCnotallow=null 時的調用棧,可以使用 harmony 進行實時跟蹤,即對 AssemblyLoadContext 構造函數(shù)進行注入,在后綴補丁中獲取 _nativeAssemblyLoadContext 值即可,這里借助上一篇的 CustomAssemblyLoadContext 代碼例子,參考代碼如下:

[HarmonyPatch(typeof(AssemblyLoadContext), MethodType.Constructor, new Type[] { typeof(string), typeof(bool) })]
    publicclassAssemblyLoadContextHook
    {
        // 后綴補丁 - 在原始方法執(zhí)行后運行
        public static void Postfix(AssemblyLoadContext __instance, IntPtr ____nativeAssemblyLoadContext)
        {
            Console.WriteLine("----------------------------");

            long addr = (____nativeAssemblyLoadContext == IntPtr.Zero) ? 0 : ____nativeAssemblyLoadContext.ToInt64();

            Console.WriteLine($"____nativeAssemblyLoadContext: 0x{addr:X}");
            Console.WriteLine(JsonConvert.SerializeObject(__instance));
            Console.WriteLine("----------------------------");
            Console.WriteLine(Environment.StackTrace);
        }
    }

圖片圖片

從卦中可以清晰的看到 new AssemblyLoadContext 之后的類型信息,并記錄了當前的調用棧,一旦有 null 出現(xiàn)的時候,是不是一下子就縮小了包圍圈哈。。。

三、總結

這次生產(chǎn)事故也強烈的警示了大家,能用 using 就不要讓 終結器線程 兜底,后者一旦崩潰就會釀成災難性后果。

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

2023-06-29 17:55:00

.NET日志WinDbg

2024-03-28 12:56:36

2025-10-29 01:11:00

.NET系統(tǒng)windows

2024-07-09 11:51:20

Windows線程池源碼

2023-03-26 20:24:50

ERP網(wǎng)站系統(tǒng)

2024-03-26 00:44:53

.NETCIM系統(tǒng)

2024-12-27 13:31:18

.NETdump調試

2023-06-26 00:12:46

2024-06-04 10:54:34

.NET代碼程序

2022-10-25 14:17:01

.NET代碼程序

2024-05-31 12:56:06

.NET代碼方法

2024-07-12 11:20:34

.NET崩潰視覺程序

2022-01-17 21:28:36

管理系統(tǒng).NET

2024-06-13 17:09:55

2021-11-02 07:54:41

內存.NET 系統(tǒng)

2023-04-06 10:52:18

2024-08-27 13:08:50

2024-07-01 13:00:24

.NET網(wǎng)絡邊緣計算

2024-11-29 10:06:59

2023-07-31 22:29:20

CPU.NETAPI
點贊
收藏

51CTO技術棧公眾號