Linux Debugging(八): core真的那麼難以追蹤嗎?

來源:互聯網
上載者:User

標籤:linux debugging   調試   core分析   dump分析   線程變數   

本周遇到了好幾個core都很有典型性。在這裡和大家分享下。

相信有過Linux編程經驗的人,肯定都遇到過。感覺周圍人很多對core有天然的恐懼感,尤其對剛入行不久的同學來說。當然了,也有工作好幾年看到core也束手無策的。今天就分析一下,core,其實大部分都是很容易解決的。如果一個core很難以複現,那麼說明還是很複雜的,算是Corner case,可能需要很長時間,腦子裡要有很好的運行時狀態才可以(閱讀源碼,學習的是邏輯;將源碼對應到運行時的狀態,分析一些狀態機器的轉換,再去分析可能會發生的情況)。相信前幾篇文章會對這種Corner case的分析與解決打下比較好的基礎。

相反,那種每次必現,或者複現比率非常高的case,是非常容易解決的。


多線程必然出core?

如果是你新加入的代碼引入的core,實際上非常容易解決的,簡單的對比一下修改的diff,然後看一下是否有比較低級的錯誤。如果發現不了,看是否是多線程的問題?單線程如果沒有出core,改成多線程就出core,那麼就說明多線程競爭某些變數了:同時修改某些變數導致出問題。這個時候你可能第一反應會加鎖。我本人非常反感加鎖;即使你加鎖的粒度很小,範圍也夠小,但是只要是加鎖,就代表有阻塞,就代表維護起來會很麻煩。這些共用變數真的那麼值得加鎖嗎?可否換成局部變數?如果他是一塊動態記憶體,為了調用某個介面時不要頻繁申請釋放記憶體(比如這個介面每秒幾千次的調用),那麼初始化時候申請一塊記憶體是絕對合理的:請把它設定為線程變數吧。每個線程初始化時候申請這塊記憶體。

當然了你如果實現的是一個架構或者架構調用的介面,這個介面要做到安全執行緒的。那麼看起來你並不能控制這個線程什麼時候啟動;線程數目會是多少個,那麼就沒有辦法了嗎?

實際上,方法有很多,比如,你可以在一個map中維護一個“線程”變數的對應關係

__gnu_cxx::hash_map< pid_t, void *> thread_data_map;void * thread_buffer;std::map<pid_t, void *>::iterator it;lockit = thread_data_map.find(pid);if (it == thread_data_map.end()) {    //init "thread data"    thread_data_map[pid] = create_buffer();} else {    thread_buffer = it->second;}unlock


這裡不得不使用了一個鎖。實際上由於線程數是有限的,因此這個效率還好。我本周實現了一個qps可以達到2000+的線上應用,基本上鎖的代價在整個的call stack中可以忽略不計。

當然了,比較好的架構可能會提供OnThreadInit這種介面,那麼在這邊申請線程變數吧:

int pthread_setspecific (pthread_key_t key, const void *value);

在實現邏輯的函數擷取該變數即可:

void *pthread_getspecific (pthread_key_t key);

什麼時候要使用線程變數?看多線程下是否對該變數有寫操作,如果有就要申請線程變數(或者加鎖),否則必然出core。


不要給自己埋下一個坑:


今天一個同學的core看起來是做了一個“最佳化”,節省了申請變數的時間。

void init() {    my_struct * some_var;    ...    some_var->res = new some_res;    some_var->res->set_value1(some_common_value1);    some_var->res->set_value2(some_common_value2);}void * thread_func(my_struct * some_var) {         some_var->res->set_value3(value_3);   ...}

set_value3就是一個出core的原因。這個也是一個典型的多線程必然出core的case。實際上,res沒必要提前申請吧。把它改成一個局部變數,效能幾乎沒有的損耗。當然了,如果這個資源很大,那麼就當成線程變數吧。


那麼如何分析core?

實際上,上述的情境出現的core如果僅從core本身,可能一時不好排查問題出在哪裡;而且core的位置可能還不一樣,不可避免的出現替罪羊;比如調用第三方的模組,實際上是自己的全域變數導致到了第三方的調用棧時出core了。因此一定要排查自己的處理是否正確。

確定調用的介面是否安全執行緒;如果是你的同事,你得確定他說的是對的。就像今天又另外的一個core,調用者堅稱他寫的是安全執行緒的,彷彿不是安全執行緒的就像是代碼寫的不好似得;最後排查出他寫的代碼不是安全執行緒時,他問你什麼是安全執行緒的。

那麼回答一下,如何分析core?

首先瞭解清楚core出現的應用情境,比如長句子處理會有core;多執行緒會有core;特殊字元會有core;這個QA會給你一個比較清楚的說明。然後通過core的call stack去大概確定大概的源碼位置。

源碼面前,了無秘密。

你讀源碼,它展現的是邏輯;但是你腦中,要有個runtime的運行時調用棧,多線程的調度;天馬行空。

當然了,還是解決不了,開始從core得到更詳細的資訊吧!看看調用棧的參數是什麼,切換一個線程看看其他的幾個線程的frame是什麼。

還解決不了?

那麼它是Corner case,只要把應用在core後立即啟動就行了。記得EMC有個bug的選項是unable to root cause, 形容的很貼切。同時不要忘記自我安慰:碼的碼多了,肯定有bug,誰能保證服務100%呢?


Linux Debugging(八): core真的那麼難以追蹤嗎?

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.