2

我正在開發一個使用GCD運行大量後臺作業的MacOS X應用程序。後臺作業使用CLucene來索引文檔,並在子上下文中訪問核心數據。使用dispatch_semaphore_t併發隊列中的死鎖

這些作業都是在短時間內產生的(在DISPATCH_QUEUE_CONCURRENT創建的隊列上使用dispatch_async),但只有4個同時執行實際工作。這是通過使用dispatch_semaphore_t完成的,通過在作業開始時等待並在作業完成時釋放它。

我看到,當一個很奇怪的,可靠的可重複的僵局:

  1. 後臺作業仍在運行
  2. 用戶焦點切換到另一個應用程序,然後回

NSWindow被顯然嘗試在顯示菜單欄時發送通知時出現死鎖。這是主線程的堆棧跟蹤,當發生這種情況:


#0 0x00007fff870ae6c2 in semaphore_wait_trap() 
#1 0x00007fff8b1bf486 in _dispatch_semaphore_wait_slow() 
#2 0x00007fff8b69c12b in -[_NSDNXPCConnection sendMessage:waitForAck:]() 
#3 0x00007fff8b57ced5 in _CFXNotificationPost() 
#4 0x00007fff8b58bbf3 in CFNotificationCenterPostNotification() 
#5 0x00007fff902ae174 in HIS_XPC_CFNotificationCenterPostNotification() 
#6 0x00007fff8bd3612a in BroadcastToolboxMessage() 
#7 0x00007fff8bd6d063 in MenuBarInstance::Show(MenuBarAnimationStyle, unsigned char, unsigned char, unsigned char)() 
#8 0x00007fff8bd98144 in SetMenuBarObscured() 
#9 0x00007fff8bd97e0f in HIApplication::HandleActivated(OpaqueEventRef*, unsigned char, OpaqueWindowPtr*)() 
#10 0x00007fff8bd95407 in HIApplication::EventObserver(unsigned int, OpaqueEventRef*, void*)() 
#11 0x00007fff8bd636e0 in _NotifyEventLoopObservers() 
#12 0x00007fff898dc018 in -[NSWindow sendEvent:]() 
#13 0x00007fff898d8744 in -[NSApplication sendEvent:]() 
#14 0x00007fff897ee2fa in -[NSApplication run]() 
#15 0x00007fff89792cb6 in NSApplicationMain() 
#16 0x0000000100001e52 in main at /Users/mspong/dev/Indx/Indx/Indx/main.m:13 
#17 0x00007fff86b7b7e1 in start() 

所有正在運行的後臺作業完成他們的工作,但沒有進一步的工作可以訪問上述信號。每個線程都卡在semaphore_wait_trap上。

我無法想象我可能會做什麼(顯然)導致無關的信號量(包括我的和蘋果的)卡住。任何人都可以提供一些關於如何進一步調查的建議嗎?

回答

6

是否有可能碰到GCD併發隊列線程限制(64個線程),然後做一些試圖在併發隊列上工作的東西?這會在整個框架中造成隨機死鎖。

如果是這樣的話,我唯一的建議是:永不阻塞併發隊列。

+0

嗯 - 如果'[_NSDNXPCConnection sendMessage:waitForAck:]'試圖使用併發隊列,肯定會出現這種情況。 我沒有意識到併發隊列中的阻塞是不好的設計,在某些情況下我肯定排隊超過64個作業。我會重新思考我是如何處理這些工作的。 – Xtapolapocetl

+1

看起來確實是這個問題。我改寫它來使用一個任務有限的NSOperationQueue,而現在一切似乎都很好。謝謝! – Xtapolapocetl

+0

@Catfish_Man,我有類似的問題。感謝關於GCD併發隊列線程限制的提示 - 請你詳細說明我可以在哪裏閱讀它(有沒有官方文檔)? –