Dynamic Data Exchange(DDE)機制引發的卡死

有一個bug:在XP系統下,某些機器上ShellExecute在打開文件時會造成程序卡死,看了Dump文件,堆棧如下:


明ShellExecute內部使用了DDE,即Dynamic Data Exchange,動態數據交換技術。

DDE用於進程間通訊,需要兩個Windows應用程序,其中一個作爲服務器處理信息,另外一個作爲客戶機從服務器獲得信息。客戶機應用程序向當前所激活的服務器應用程序發送一條消息請求信息,服務器應用程序根據該信息作出應答,從而實現兩個程序之間的數據交換。 爲了DDE,程序A(後來卡死的程序)會使用SendMessage廣播WM_DDE_INITIATE 消息,其他程序收到WM_DDE_INITIATE 後根據參數決定是否處理該消息,處理的話返回一個WM_DDE_ACK 消息,否則就什麼都不做。假設,收到WM_DDE_INITIATE 的程序中有那麼幾個程序阻塞的處理了這個消息(比如sleep(100000)或者幹了一些其他很耗時的事情),那我們的程序A就悲劇了,它將一直等待,一直等待,一直等待......會不會就這麼一直等待下去?答案是no,看上面的堆棧,有一個SendMessageTimeOut,DDE使用的是帶超時控制的SendMessage,在無響應後一段時間內(對於DDE這裏,是30s,太卡怕了),程序A將繼續執行,這也就是ShellExecute卡一段時間的原因,有可能是卡了超時的30s,也有可能是卡了多個程序響應WM_DDE_INITIATE 花的時間的累加。

其實DDE技術是一項過時的技術,它適用於16位系統下的進城間通信,比如Windows Shell 外殼打開某些文件類型(這不就是我們用的ShellExecute麼?!),win7下已經放棄了,但是xp下爲了兼容一些16的程序還是保留了。

那麼爲什麼DDE在16系統下沒問題在32位就不行了呢?

看這裏:


16位系統是co-operatively multitasking系統,即合作式系統,充分信任每一個task,讓它一直獨佔CPU,直到它自己把CPU用煩了,這樣的缺點很明顯:如果有一些很戳的程序很不自覺的長時間佔用CPU,那其他程序就無法得到CPU執行,更嚴重的是,整個系統也將被卡住!!但是這樣也保證了類似於DDE的廣播技術可以實施而不用擔心會無響應卡住。

以後的per-emptive multitasking系統,即搶佔式系統,系統充分參與調度,並且給每個task一個執行時間限制。而在windows系統下(也是per-emptive multitasking系統),由於調度策略是“飢餓策略”(調度策略有多重,可以參考這裏),對於廣播技術,就可能造成A程序廣播後,B程序拿到CPU執行權,然後他響應了廣播消息,但是一直佔用CPU,這時A就卡死了。

具體的各種CPU模型和調度可以看這裏,主要是分時系統啦



知道原因後,這個卡死的問題也可以解決,猥瑣且迅速的方法就是改掉SendMessageTimeout的超時時間限制,ShellExecute用DDE時默認設置的是30s,自己的程序Hook住SendMessageTimeout後將超時時間改小一些就好了。比如10ms?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章