記一次程序coredump定位

問題背景

最近在做pika的新存儲引擎BlobKV開發(fā),所謂的BlobKV就是將key和value分開存儲,目的是解決大value情況下,rocksdb compaction導(dǎo)致的寫放大問題。由于新的存儲引擎和舊的存儲引擎在數(shù)據(jù)格式上的不兼容,所以需要將舊的存儲引擎數(shù)據(jù)通過命令的形式遷移到新的存儲引擎上。

問題現(xiàn)象

遷移工具比較簡單,流程就是先在源端執(zhí)行Bgsave,生成數(shù)據(jù)庫的備份dump,然后開啟五個線程對五種數(shù)據(jù)類型的數(shù)據(jù)庫掃描key并且將key分發(fā)到多個遷移線程中,由遷移線程發(fā)送給對端。
問題是,在數(shù)據(jù)量較大時,每次都是遷移到一定的數(shù)據(jù)量,遷移程序就會自動退出,并且沒有打印任何退出前的日志:-(

問題定位

  1. 程序非正常退出,首先想到的是看有沒有生成coredump文件,查看了下,沒有生成coredump文件。
  2. 然后查看系統(tǒng)的dmesg,發(fā)現(xiàn)一個遷移線程退出的日志,分配內(nèi)存失敗,原因是free內(nèi)存太少,于是釋放了系統(tǒng)的頁緩存。重新遷移,發(fā)現(xiàn)還是會自動退出,但demsg中已經(jīng)沒有錯誤日志了,所以也排除了OOM殺死進程。
  3. 繼續(xù)查看系統(tǒng)的messages日志,執(zhí)行cat /var/log/messages,發(fā)現(xiàn)也是沒有任何信息
  4. 再看遷移程序中的日志,也沒有發(fā)現(xiàn)任何ERROR日志(遷移程序非正常退出時候都會打印ERROR日志)
  5. 程序就這樣死的一點遺言都沒有,很是絕望。但仔細(xì)想想,既然程序不是主動退出,那肯定是被系統(tǒng)殺死的,系統(tǒng)怎么殺死進程呢?--發(fā)信號量啊。于是抱著最后一根救命稻草,我在程序里捕獲了所有信號量(31個系統(tǒng)經(jīng)常發(fā)的信號)。

終于,兇手抓住了??! 系統(tǒng)給遷移進程發(fā)了一個SIGPIPE信號,該信號的意思是“管道破損,沒有讀端的管道寫數(shù)據(jù)”,也就是說對端將遷移線程的連接給斷開了,此時發(fā)送線程在寫一個不可讀的管道,導(dǎo)致程序退出....

問題解決

  1. 遷移程序忽略SIGPIPE信號
  2. 將對端連接超時斷開的時間從60s改成了600s
  3. 遷移線程發(fā)送失敗后,嘗試重新連接,而不是直接退出

問題思考

  1. 對端為什么會將遷移線程的連接斷開,按理說遷移線程一直在發(fā)送數(shù)據(jù),不可能是在非活躍狀態(tài)。(需要進一步調(diào)查)
  2. 在寫socket程序時記得要忽略SIGPIPE信號量
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容