上回處理過WebSocket導致Mac Safari當機,修復後狀況明顯改善,但有時仍重新載入網頁時Safari仍會當掉,而錯誤訊息模糊許多:

Process:         com.apple.WebKit.WebContent [1527]
Path:            /System/Library/PrivateFrameworks/WebKit2.framework/Versions/A/XPCServices
/com.apple.WebKit.WebContent.xpc/Contents/MacOS/com.apple.WebKit.WebContent
Identifier:      com.apple.WebKit.WebContent
Version:         9537 (9537.71)
Build Info:      WebKit2-7537071000000000~3
Code Type:       X86-64 (Native)
Parent Process:  ??? [1]
Responsible:     Safari [1109]
User ID:         501

Date/Time:       2014-04-11 17:09:51.606 +0800
OS Version:      Mac OS X 10.9 (13A603)
Report Version:  11
Anonymous UUID:  F8190022-15F6-1032-03AC-3B2053B998AE
Sleep/Wake UUID: EE71F795-BA3F-43AE-A1E6-143B4B4AFEBD

Crashed Thread:  0  Dispatch queue: com.apple.main-thread

Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: EXC_I386_GPFLT

Application Specific Information:
Bundle controller class:
BrowserBundleController
 
Process Model:
Multiple Web Processes

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   com.apple.WebCore                 0x00007fff9190523a void std::__1::__push_heap_front<WebCore::TimerHeapLessThanFunction&, WebCore::TimerHeapIterator>(WebCore::TimerHeapIterator, WebCore::TimerHeapIterator, WebCore::TimerHeapLessThanFunction&, std::__1::iterator_traits<WebCore::TimerHeapIterator>::difference_type) + 186
1   com.apple.WebCore                 0x00007fff918790c7 WebCore::TimerBase::heapPopMin() + 135
2   com.apple.WebCore                 0x00007fff918783c8 WebCore::TimerBase::updateHeapIfNeeded(double) + 280
3   com.apple.WebCore                 0x00007fff91875e00 WebCore::TimerBase::setNextFireTime(double) + 192
4   com.apple.WebCore                 0x00007fff91907a1b WebCore::FrameView::layout(bool) + 107
5   com.apple.WebCore                 0x00007fff91a0b681
(...以下省略...)

EXC_I386_GPFLT是所謂一般性失敗,EXC_BAD_ACCESS則程式存取範圍外的記憶體區塊,是程式錯亂的標準症狀,二者都沒什麼營養。唯一有價值的線索是Callstack有Timer字樣,讓我懷疑跟setTimer、setInterval有關,雖然這樣就把瀏覽器搞掛不合邏輯,我仍試著停用網頁的setTimer、setInterval碰碰運氣,反覆測試均不見效果,射手開始茫然...

瞎試一陣子後,發現重大情資 -- 網站裝在四個不同測試機上,只有兩台(A,B)會導致Safari當機,另外兩台測試台(C,D)從沒把Safari搞掛過! A,B,C是Windows 2012,D是"Windows 2008"。靈機一動,該不會又跟WebSocket有關吧? 檢查後證實,測試機C雖是Windows 2012因IIS設定問題,跟D一樣沒啟用WebSocket,而A,B有成功啟用WebSocket。這點意外成為破案關鍵,Safari當機的原因,繞了一大圈,最後又回到WebSocket上。

幾經嘗試,最後我找到的解法是在window.onbeforeunload事件加入一小段程式,在離開網頁前主動關閉SignalR連線。

window.onbeforeunload = function () {
    try {
        if ($.connection && $.connection.hub) {
            $.connection.hub.stop();
        }
    }
    catch (ex) {  }
    finally {  }
}

從此之後,SignalR網頁就跟Safari過著幸福快樂的日子了... (希望如此啦)

2014-05-14更新,找到相同Issue的討論,網友的解法也相同,而此一Bug已於2.0.2版修正


Comments

Be the first to post a comment

Post a comment