《Windows 用戶態程序高效排錯》市場價元 特價元 購買>>
本可以做得更好SharePoint中文界面變英文
問題描述
Windows SharePoint Portal 是運行在NET Framework上的一個web應用程序管理員可以設定使用英文界面或者中文界面某天一個客戶抱怨SharePoint無法顯示中文界面所有的頁面都用英文顯示經過仔細觀察發現下面的現象:
管理員的設定值是中文界面
該程序在過去的一年中都運行正常
大多數情況下中文界面工作正常
偶然有幾次中文界面會變成英文界面
變成英文界面後過一段時間後會自動變回中文界面
變成英文界面後如果重新啟動IIS 有可能解決問題
排錯步驟
經過觀察發現客戶的安裝和配置是沒有問題的大致調試後發現:
客戶程序工作線程的UI Culture的確是zhcn 跟客戶的設定一致
界面顯示資源是通過ResourceManagerGetString系統方法來加載的
ResourceManagerGetString
http://msdnmicrosoftcom/enus/systemresourcesresourcemanagergetstringaspx
該客戶的中文資源衛星文件安裝正確
根據這個信息GetString應該返回對應的中文資源但是在問題發生的時候返回的卻是英文資源所以需要解釋的是這個NET系統方法為何表現異常面臨的難點是
無法簡單重現問題需要反復重新啟動IIS多次後問題才會偶然發生
問題只有在客戶機器上才能重現需要遠程調試操作起來不是很方便
由於出問題的代碼是NET Framework的函數不是客戶的代碼沒辦法用第個例子的方法來添加log分析
當時歐洲很多客戶也有類似問題發生比如西班牙語的站點變成了英語日本更是嚴重有十幾個站點都有這個問題但是幾個星期來一直都沒有找到問題的根源
由於問題的線索是GetString方法的異常表現所以排錯計劃也非常直接跟蹤GetString的執行過程在做遠程調試以前首先在本地跟蹤GetString的執行過程來理解邏輯大致的邏輯是
資源符號從衛星加載起來後會放到內存的HashTable中
GetString檢查HashTable中是否有請求的資源如果有跳到第步
如果沒有GetString會讓ResourceManager根據當前線程的UI Culture尋找對應衛星目錄來加載
ResourceManager加載衛星Assembly到內存同時把所有的資源符號都寫入HashTable
GetString返回這個HashTable中對應的資源
如果有問題發生比如ResourceManager沒有找到對應的衛星目錄或者資源文件不存在就用中立語言(英語)資源代替
一旦HashTable填充完成GetString的後繼執行就不需要使用ResourceManager了直接返回HashTable的內容
根據上面的邏輯客戶那裡的問題很可能是ResourceManager沒有找到資源文件於是就用英語初始化HashTable根據這個信息決定用Filemon來檢視資源文件的訪問可惜的是Filemon的結果表明每次對資源文件的訪問都是成功的同時再次檢查了資源文件的安裝也沒有發現異常
走投無路的時候只有通過遠程調試來檢查了跟客戶交流後客戶同意在把晚上點到早上點的時間段留給我們來排錯為了排除干擾用下面的步驟來檢查
在IIS上限制只有測試用客戶端IP才能訪問
把IIS和ASPNET的超時時間都設定到無限長
每次調試前重新啟動IIS
在客戶端刷新一次頁面然後在調試器中檢查GetString和ResourceManager的執行過程
限制IP的目的是為了控制重現問題的時機防止有其他用戶來訪問頁面重新啟動IIS是必須的因為要觀察HashTable的初始化過程設定超時時間是為了防止超時異常干擾調試在連續幾天的努力後發現下面的線索
加載衛星文件的時候失敗了
加載過程中有兩次first chance CLR exception
問題發生的時候執行了一些異常的codepath這個codepath上很多函數的名字比較新穎在本地測試的時候沒看到類似的函數
根據上面的結果重新在本地檢查對應的代碼然後結合wt命令和異常發生的時機抓取某些codepath的執行過程分析後發現一個比較重要的線索客戶那裡部署了NET Framework SP一些SP中新加入的codepath被執行到了
經過最後的整理和分析發現了問題是這樣的在NET Framework 上ResourceManager判斷當前線程的UI Culture後就開始尋找對應的衛星文件但是SP中添加了某一個額外的配置選項使得尋找的過程可以通過webconfig來配置由於 webconfig配置文件很重要普通的web用戶是沒有權限訪問的在訪問webconfig過程中一旦發生了Access Denied就會導致CLR exception異常發生後ResourceManager認為某些地方出了問題於是ResourceManager停止加載衛星文件用中立資源代替於是英文就代替了中文
換句話說設計者沒有考慮到web程序中沒有權限去訪問CLR程序配置文件(web程序中是webconfig)的情況是很常見的這種情況沒有被特殊處理因而導致了問題
在客戶重新啟動IIS後如果程序第一個使用者權限比較高能夠訪問webconfig的話中文資源就可以加載起來如果第一個使用者權限比較低問題就發生了而且會一直保留到下一次IIS重新啟動再次加載資源的時候暫時的解決方法是把webconfig設定為Everyone Access Allow這個workaround在一個星期內迅速幫助了全球范圍內很多SPS站點的顯示正常起來
當然修改webconfig的權限是非常危險的所以申請一個hotfix才是最終的解決方案
FIX: Your application cannot load resources from a satellite assembly if the impersonated user account does not have permissions to access the application config file in the NET Framework Service Pack
http://supportmicrosoftcom/?id=
錯過的線索
如果仔細分析這個案例的解決過程 會發現排錯初期距離勝利就只有一步之遙已經想到了用Filemon去觀察衛星文件的訪問情況但是就沒想到用Filemon觀察裡面是否有Access Denied事後拿出當時的Filemon結果查找Access Denied一共發現了幾處同時當觀察到該問題以前一直沒有現在突然像洪水一樣全球泛濫時就應該意識到最近一段時間發布的一些重要補丁很可疑
所以如果想做得更好一點不在於使用了多少工具用了多麼深奧的調試技術而在於能夠比經驗主義多想到一點什麼開拓一下思路可以很簡單地四兩拔千斤
這一章不在於演示出一套分析問題的模版而是想說明解決問題的核心武器是思考知識和工具只是輔助在遇上問題的時候能夠多想一分鐘再動手本章的目的就達到了
From:http://tw.wingwit.com/Article/os/xtgl/201311/10166.html