聊一聊 .NET Dump 中的 Linux信號機制

一:背景

1. 講故事

.NET程序 在Linux上崩潰時,我們可以配置一些參考拿到對應程序的core文件,拿到core文件后用windbg打開,往往會看到這樣的一句信息 Signal SIGABRT code SI_USER (Sent by kill, sigsend, raise),參考如下:


(1.1d): Signal SIGABRT code SI_USER (Sent by kill, sigsend, raise)
libc_so!wait4+0x57:
00007fbd`09313c17 483d00f0ffff    cmp     rax,0FFFFFFFFFFFFF000h
0:023> ? 1d
Evaluate expression: 29 = 00000000`0000001d
0:023> ~29s
*** WARNING: Unable to verify timestamp for libSystem.Native.so
libc_so!read+0x4c:
00007fbd`0933829c 483d00f0ffff    cmp     rax,0FFFFFFFFFFFFF000h

從字面上看是 kill,sigsend,raise 發出了攜帶 SI_USER 代碼的 SIGABRT 信號,看起來和Linux信號機制有關,那具體是什么意思呢?這就是本篇和大家詳聊的。

二:Linux 信號機制

1. 信號機制簡介

簡單的說Linux信號是一種進程間通信機制,大概可以做三件事情。

  • 通知進程發生了某種事件,比如:段錯誤。
  • 允許進程間發送簡單的消息。
  • 控制進程行為,比如:終止、暫停、繼續等。

在 linux 上有60多個信號,默認能產生core文件的有11個,這也是我們最關心的,整理成表格如下:

信號名稱信號編號說明
SIGQUIT3通常由 Ctrl+\ 觸發
SIGILL4非法指令
SIGABRT6由 abort() 函數產生
SIGFPE8浮點異常
SIGSEGV11段錯誤(非法內存訪問)
SIGBUS7總線錯誤(內存訪問對齊問題等)
SIGSYS31錯誤的系統調用
SIGTRAP5跟蹤/斷點陷阱
SIGXCPU24超出 CPU 時間限制
SIGXFSZ25超出文件大小限制
SIGEMT7EMT 指令(某些架構)

有了這些基礎之后就可以解讀 Signal SIGABRT code SI_USER (Sent by kill, sigsend, raise) 這句話了。

1) SIGABRT

全稱 signal abort ,是一種能產生 core 的信號。

2) SI_USER

在 linux 源碼中有這樣一句代碼(type == PIDTYPE_PID) ? SI_TKILL : SI_USER,參考如下:


static void prepare_kill_siginfo(int sig, struct kernel_siginfo *info,enum pid_type type)
{clear_siginfo(info);info->si_signo = sig;info->si_errno = 0;info->si_code = (type == PIDTYPE_PID) ? SI_TKILL : SI_USER;info->si_pid = task_tgid_vnr(current);info->si_uid = from_kuid_munged(current_user_ns(), current_uid());
}

代碼中的 kernel_siginfo.si_code 字段用來表示信號的來源,比如說 SI_USER 表示信號來源于用戶進程,而后者的 SI_TKILL 表示信號來源于 tgkill,tkill 系統調用。

3) kill,sigsend,raise

熟悉 linux 的朋友應該對 killraise 方法非常熟悉,畢竟他們遵守 POSIX 標準,至于他們有什么區別,看簽名就知道了。。。


/* Raise signal SIG, i.e., send SIG to yourself.  */
extern int raise (int __sig) __THROW;/* Send signal SIG to process number PID.  If PID is zero,send SIG to all processes in the current process's process group.If PID is < -1, send SIG to all processes in process group - PID.  */
#ifdef __USE_POSIX
extern int kill (__pid_t __pid, int __sig) __THROW;
#endif /* Use POSIX.  */

相比前面的函數,這個 sigsend 就不是 POSIX 標準了,只在部分Unix上可用,比如 Solaris,SunOS,不過功能還是很強大的,不僅可以指定 pid,還可以指定 pidgroup 以及 user 來批量的 kill 進程,這里做個了解即可,簽名如下:


int sigsend(idtype_t idtype, id_t id, int sig);

這些信息匯總之后更準確的意思就是:你的程序可能調用了 kill(SIGABRT) ,raise(SIGABRT),abort 引發的程序崩潰,那是不是這樣的呢?可以用 windbg 的 ~* k 觀察每個線程的調用棧,最終還真給找到了。


0:023> k# Child-SP          RetAddr               Call Site
00 00007fbd`03c62a70 00007fbd`090bf635     libc_so!wait4+0x57
01 00007fbd`03c62aa0 00007fbd`090c0580     libcoreclr!PROCCreateCrashDump+0x275 [/__w/1/s/src/coreclr/pal/src/thread/process.cpp @ 2307] 
02 00007fbd`03c62b00 00007fbd`090be22f     libcoreclr!PROCCreateCrashDumpIfEnabled+0x770 [/__w/1/s/src/coreclr/pal/src/thread/process.cpp @ 2524] 
03 00007fbd`03c62b90 00007fbd`090be159 (T) libcoreclr!PROCAbort+0x2f [/__w/1/s/src/coreclr/pal/src/thread/process.cpp @ 2555] 
04 (Inline Function) --------`-------- (T) libcoreclr!PROCEndProcess+0x7c [/__w/1/s/src/coreclr/pal/src/thread/process.cpp @ 1352] 
05 00007fbd`03c62bb0 00007fbd`08db667f (T) libcoreclr!TerminateProcess+0x84 [/__w/1/s/src/coreclr/pal/inc/pal_mstypes.h @ 1249] 
...
09 00007fbd`03c63950 00007fbd`08d4524e     libcoreclr!UMEntryThunk::Terminate+0x38 [/__w/1/s/src/coreclr/inc/clrtypes.h @ 260] 
0a (Inline Function) --------`--------     libcoreclr!InteropSyncBlockInfo::FreeUMEntryThunk+0x24 [/__w/1/s/src/coreclr/vm/syncblk.cpp @ 119] 
19 00007fbd`03c63e30 00007fbd`092c91f5     libcoreclr!CorUnix::CPalThread::ThreadEntry+0x1fe [/__w/1/s/src/coreclr/pal/inc/pal.h @ 1763] 
1a 00007fbd`03c63ee0 00007fbd`09348b00     libc_so!pthread_condattr_setpshared+0x515
1b 00007fbd`03c63f80 ffffffff`ffffffff     libc_so!_clone+0x40
1c 00007fbd`03c63f88 00000000`00000000     0xffffffff`ffffffff

在上面的代碼中我們看到了 libcoreclr!PROCAbort 函數,在 coreclr 中方法定義如下:


/*++
Function:PROCAbort()Aborts the process after calling the shutdown cleanup handler. This functionshould be called instead of calling abort() directly.Parameters:signal - POSIX signal numberDoes not return
--*/
PAL_NORETURN
VOID
PROCAbort(int signal)
{// Do any shutdown cleanup before aborting or creating a core dumpPROCNotifyProcessShutdown();PROCCreateCrashDumpIfEnabled(signal);// Restore the SIGABORT handler to prevent recursionSEHCleanupAbort();// Abort the process after waiting for the core dump to completeabort();
}VOID PROCCreateCrashDumpIfEnabled(int signal, siginfo_t* siginfo, bool serialize)
{// If enabled, launch the create minidump utility and wait until it completesif (!g_argvCreateDump.empty()){std::vector<const char*> argv(g_argvCreateDump);...}
}

卦中的代碼邏輯非常清楚,在 abort 退出之前,先通過 PROCCreateCrashDumpIfEnabled(signal) 方法踩了一個dump,也就是說 dump 中看到的信息就是用他來填充的,可以觀察 libcoreclr!g_argvCreateDump 全局變量,參考如下:


0:023> x libcoreclr!*g_argvCreateDump*
00007fbd`09192360 libcoreclr!g_argvCreateDump = {size=8}
0:023> dx -r1 (*((libcoreclr!std::vector<const char *, std::allocator<const char *> > *)0x7fbd09192360))
(*((libcoreclr!std::vector<const char *, std::allocator<const char *> > *)0x7fbd09192360))                 : {size=8} [Type: std::vector<const char *, std::allocator<const char *> >][<Raw View>]     [Type: std::vector<const char *, std::allocator<const char *> >][size]           : 8[capacity]       : 8[0]              : 0x5555b5d71140 : "/usr/share/dotnet/shared/Microsoft.NETCore.App/8.0.15/createdump" [Type: char *][1]              : 0x7fbd08b61d8f : "--name" [Type: char *][2]              : 0x7ffd1b7e1cec : "/db/xxxx/crash.dmp" [Type: char *][3]              : 0x7fbd08b6ce5f : "--full" [Type: char *][4]              : 0x7fbd08b4c7ee : "--diag" [Type: char *][5]              : 0x7fbd08b58630 : "--crashreport" [Type: char *][6]              : 0x5555b5dd7230 : "1" [Type: char *][7]              : 0x0 [Type: char *]

2. C代碼眼見為實

為了能夠讓大家有一個更加貼切的眼見為實,我們用 C 代碼親自演示一下,為產生 core 文件,配置如下:


root@ubuntu2404:/data2# ulimit -c unlimited 
root@ubuntu2404:/data2# echo /data2/core-%e-%p-%t  | sudo tee /proc/sys/kernel/core_pattern
/data2/core-%e-%p-%t

配置好之后,大家可以使用 abort,kill,raise 這三個方法的任何一個,這里我就用 kill 來演示吧。


#include <stdio.h>
#include <signal.h>
#include <unistd.h>void sig_handler(int signo, siginfo_t *info, void *context)
{fprintf(stderr, "Received signal: %d (sent by PID: %d, UID: %d)\n",signo, info->si_pid, info->si_uid);
}int main()
{struct sigaction sa;sa.sa_sigaction = sig_handler;sa.sa_flags = SIGABRT;sigemptyset(&sa.sa_mask);if (sigaction(SIGSEGV, &sa, NULL) == -1){perror("sigaction");return 1;}printf("My PID: %d\n", getpid());printf("Press Enter to send SIGABRT to myself...\n");getchar();kill(getpid(), SIGABRT);  // 第一種方式// raise(SIGABRT);        // 第二種方式//  abort();              //第三方方式printf("This line may not be reached.\n");return 0;
}

ternimal 如下:


root@ubuntu2404:/data2# ./app
My PID: 7403
Press Enter to send SIGABRT to myself...Aborted (core dumped)
root@ubuntu2404:/data2# 
root@ubuntu2404:/data2# ls -lh
total 160K
-rwxr-xr-x 1 root root  21K May 27 10:25 app
-rw-r--r-- 1 root root  813 May 27 10:25 app.c
-rw------- 1 root root 432K May 27 10:25 core-app-7403-1748312729

用 windbg 打開 core-app-7403-1748312729 文件,熟悉的畫面又回來了,哈哈。截圖如下:

三:總結

要分析linux 上的.NET程序崩潰,理解Linux信號機制是一個必須要過的基礎,調試之路艱難哈。。。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/81568.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/81568.shtml
英文地址,請注明出處:http://en.pswp.cn/web/81568.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

如何在uniapp H5中實現路由守衛

目錄 Vue3 app.config.globalProperties 1. 創建 Vue 應用實例 2. 添加全局屬性或方法 3. 在組件中使用全局屬性或方法 beforeEach在uniapp的注冊 1、在H5中這兩個對象是都存在的。「router:route」但是功能并不全面,具體可參考下圖。 2、剛剛測試了一下,在微信小程序…

無人機降落傘設計要點難點及原理!

一、設計要點 1. 傘體結構與折疊方式 傘體需采用輕量化且高強度的材料&#xff08;如抗撕裂尼龍或芳綸纖維&#xff09;&#xff0c;并通過多重折疊設計&#xff08;如三重折疊縫合&#xff09;減少展開時的阻力&#xff0c;同時增強局部承力區域的強度。 傘衣的幾何參數&am…

AI時代新詞-AI增強現實(AI - Enhanced Reality)

一、什么是AI增強現實&#xff08;AI - Enhanced Reality&#xff09;&#xff1f; AI增強現實&#xff08;AI - Enhanced Reality&#xff09;是指將人工智能&#xff08;AI&#xff09;技術與增強現實&#xff08;Augmented Reality&#xff0c;簡稱AR&#xff09;技術相結合…

基于Matlab實現各種光譜數據預處理

在IT領域&#xff0c;尤其是在數據分析和科學研究中&#xff0c;光譜數據的預處理是至關重要的步驟。光譜數據通常包含了豐富的信息&#xff0c;但往往受到噪聲、雜散光、背景信號等因素的影響&#xff0c;需要通過預處理來提取有效信號&#xff0c;提高分析的準確性和可靠性。…

用 commitizen-go 來實現標準化你的Git提交信息 【windows 版】

前言 團隊中有部分人的 commit 信息比較隨意&#xff0c;因此想用工具來進行約束&#xff0c; web 項目可以使用 commitizen 來實現&#xff0c; 但是 golang 又該用什么來約束呢&#xff0c; 在 Github 上找到 commitizen-go 可以做為 commitizen 平替&#xff0c;但該說明文…

為什么共現矩陣是高維稀疏的

為什么共現矩陣是高維稀疏的&#xff1f; 共現矩陣&#xff08;Co-occurrence Matrix&#xff09;的高維稀疏性是其固有特性&#xff0c;主要由以下原因導致&#xff1a; 1. 高維性的根本原因 詞匯表大小決定維度&#xff1a; 共現矩陣的維度為 ( V \times V )&#xff0c;其…

OpenLayers 加載鼠標位置控件

注&#xff1a;當前使用的是 ol 5.3.0 版本&#xff0c;天地圖使用的key請到天地圖官網申請&#xff0c;并替換為自己的key 地圖控件是一些用來與地圖進行簡單交互的工具&#xff0c;地圖庫預先封裝好&#xff0c;可以供開發者直接使用。OpenLayers具有大部分常用的控件&#x…

知識宇宙-學習篇:學編程為什么從C語言開始學起?

名人說&#xff1a;博觀而約取&#xff0c;厚積而薄發。——蘇軾《稼說送張琥》 創作者&#xff1a;Code_流蘇(CSDN)&#xff08;一個喜歡古詩詞和編程的Coder&#x1f60a;&#xff09; 目錄 一、C語言的歷史地位與影響力1. 編程語言的"鼻祖"2. 現代技術的基礎 二、…

手機IP地址更換的影響與操作指南

在移動互聯網時代&#xff0c;IP地址如同手機的“網絡身份證”&#xff0c;其變更可能對上網體驗、隱私安全及服務訪問產生連鎖反應。無論是為了繞過地域限制、保護隱私&#xff0c;還是解決網絡沖突&#xff0c;了解IP更換的影響與正確操作方法都至關重要。本文將系統分析影響…

基于Alibaba Cloud Linux + 寶塔面板安裝 LibreOffice 全攻略流程

LibreOffice 是一款功能強大的辦公軟件,默認使用開放文檔格式 (OpenDocument Format , ODF), 并支持 *.docx, *.xlsx, *.pptx 等其他格式。 官網:https://www.libreoffice.org/ 或 https://zh-cn.libreoffice.org/ Alibaba Cloud Linux 3(Soaring Falcon) 是阿里云自主研發…

UniApp 微信小程序綁定動態樣式 :style 避坑指南

在使用 UniApp 開發跨端應用時&#xff0c;綁定動態樣式 :style 是非常常見的操作。然而&#xff0c;很多開發者在編譯為 微信小程序 時會遇到一個奇怪的問題&#xff1a; 原本在 H5 中可以正常渲染的樣式&#xff0c;在微信小程序中卻不生效&#xff01; 讓我們通過一個示例來…

WebSocket學習總結

WebSocket 是一種基于TCP的網絡通信協議&#xff0c;允許瀏覽器和服務器之間進行全雙工、實時、低延遲的雙向數據傳輸。它突破了傳統HTTP協議的限制&#xff08;請求-響應模式&#xff09;&#xff0c;特別適合需要實時通信的場景&#xff08;如聊天、實時數據推送、游戲等&…

【screen-recorder-tts】RPG 游戲字幕語音實時合成,讓無聲文字游戲變有聲

screen-recorder-tts RPG 游戲字幕語音實時合成&#xff0c;讓無聲文字游戲變有聲&#xff01; 歡迎大佬們提 PR&#xff0c;一起完善這個項目&#xff01;&#xff01;&#xff01; Real-time TTS for RPG game subtitles, turning silent text games into audio experienc…

深入解析Spring Boot與Redis的緩存集成實踐

深入解析Spring Boot與Redis的緩存集成實踐 引言 在現代Web應用中&#xff0c;緩存技術是提升系統性能的重要手段之一。Redis作為一種高性能的內存數據庫&#xff0c;廣泛應用于緩存場景。本文將詳細介紹如何在Spring Boot項目中集成Redis&#xff0c;并探討其在實際開發中的…

4月報 | SeaTunnel支持TDengine的多表Sink功能

各位熱愛 Apache SeaTunnel 的小伙伴們&#xff0c;今年 4 月份月報更新啦&#xff01;這里將記錄 SeaTunnel 社區每月的重要更新&#xff0c;歡迎關注&#xff01; 在本月的眾多更新中&#xff0c;最令人關注的一項新特性是——TDengine 多表 Sink 功能的支持&#xff08;由 …

vue項目表格甘特圖開發

?? 甘特圖可以管理項目進度,生產進度等信息,管理者可以更直觀的查看內容。 1. 基礎環境搭建 引入 dhtmlx-gantt 插件引入插件樣式 dhtmlxgantt.css引入必要的擴展模塊(如 markers、tooltip)創建 Vue 組件并掛載 DOM 容器初始化 gantt 圖表配置2. 數據準備與處理 定義任務…

華為HCIP-Cloud-Service認證H13-821V2.0-002

1.以下關于 HiLens 關鍵能力的說法錯誤的是?&#xff08;C&#xff09; A.HiLens 能提供模型優化框架、自動壓縮模型能力&#xff0c;將模型轉換為目標芯片所支持的模 型格式 B.在 HLens 平臺上開發的 Ski11 可以運行到任何基于華為海思芯片的設備上 C.HilLens 平臺只能導入從…

【教程】給Apache服務器裝上輕量級的防DDoS模塊

轉載請注明出處&#xff1a;小鋒學長生活大爆炸[xfxuezhagn.cn] 如果本文幫助到了你&#xff0c;歡迎[點贊、收藏、關注]哦~ 背景說明 最近我的網站在被人瘋狂刷流量&#xff0c;導致正常訪問都不行&#xff0c;沒辦法只好找找怎么給他限制一下。 apache自帶有一個防刷模塊mod_…

pytorch 15.2 學習率調度在PyTorch中的實現方法

文章目錄 一、優化器與狀態字典&#xff08;state_dict&#xff09;1.1 優化器相關參數介紹1.2 模型的本地保存與讀取方法 二、LambdaLR基本使用方法三、LambdaLR學習率調度實驗3.1 前期準備與匿名函數定義 學習率調度作為模型優化的重要方法&#xff0c;也集成在了PyTorch的 …

【FAQ】spring boot 3 集成 nacos

拉取依賴&#xff1a; <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-alibaba-nacos-config</artifactId><version>2023.0.3.2</version> </dependency>配置 nacos 配置 注意&#xff1a;如果配置文…