【疑難系列】 是程序卡住了仍是怎麼了?

原由

客戶說:「今天的預報又沒有發出去,幫忙看下怎麼回事?」面試

「...」windows

通過

登錄服務器,發現程序一直在打印服務器

running
running
running
...

這是代碼中寫的.net

public static void Main(string[] args)
        {
            Console.Title = string.Format("Grib2壓碼程序 請勿關閉");
            ActiveMq();
            while (hasMessage)
            {
                Console.WriteLine("running");
                Thread.Sleep(1000);
            }
        }

程序經過啓動ActiveMQ,而後判斷是否仍有消息在處理,若是在處理就Sleep當前線程,等待處理完畢線程

當接收到消息時的處理主邏輯:日誌

public static void OnMessage(IMessage message)
        {
            var msg = message as ITextMessage;
            if(msg != null)
            {
               
                hasMessage = true;
                String date = msg.Text;
                Compress(date);
                mq.send(date);
                hasMessage = false;
            }
        }

那麼問題應該是Compress或者 mq.send 一直在處理,卡住了??code

由於是.net程序,因此不能用jstack來分析線程了orm

經過windows自帶的任務管理器,把程序dump出來blog

如何dump

而後使用windbg分析一下線程,直接經過文件, "open dump file",打開導出的dmp文件。string

dump文件結果

windbg第一次使用,不是很懂得使用,可是注意到右下角threads的線程信息,發現只有一個主線程在運行!!

也就是說:咱們的監聽線程退出了!!!

那麼,什麼狀況下會退出呢?

通常是線程運行過程當中拋出異常沒有處理

檢查源代碼,發現程序沒有對出現異常作任何處理

因此,修改方案以下:

public static void OnMessage(IMessage message)
        {
            var msg = message as ITextMessage;
            if(msg != null)
            {
               
                hasMessage = true;
                String date = msg.Text;
                if(Compress(date, 3))
                {
                    mq.send(date);
                }
                else
                {
                    mq.fail(date);
                }
                hasMessage = false;
            }
        }

        public static bool Compress(string date, int retry)
        {
            if (retry == 0)
            {
                return false;
            }
            try
            {
                Compress(date);
                return true;
            }
            catch (Exception ex)
            {
                Log.writeException(ex);
                return Compress(date, retry - 1);
            }
        }

將監聽消息部分的代碼進行修改,增長重試,並進行try catch異常處理,出現異常時,在文件中記錄日誌

固然mq.send 也有可能出現異常,將send方法也進行try catch異常處理

替換程序,上線運行(這種問題看可否重現了,重現了就能夠在error.log中找到了)

總結分析

windbg第一應用,表示不少信息都看不懂

主線程中須要考慮子線程的異常,有些線程,你覺得在運行,實際上它退出了

其它

面試的時候,面試官問我

「你遇到過最難解決的問題,你是怎麼解決的?」

「我特麼都是問題解決了就忘記了,因此沒啥印象」

不過,我是在內心說的

因此,對於別人問個人問題,我決定記錄下來,省得未來忘記了

相關文章
相關標籤/搜索