2014-11-13 2 views
0

Небольшое количество клиентов получают зависаний от моего OS X приложение со следующей подвесить войти подписи:NSThread detachNewThreadSelector выполнения на главном потоке

26 ??? [0x7fff93e87fc9] 
26 ??? [0x7fff93e8372a] 
    26 ??? [0x7fff93e83899] 
    26 __NSThread__main__ + 1318 (Foundation) [0x7fff8be96dfb] 
     26 -[AppController startClean] + 1319 (Housekeeper) [0x100007742] 
     13 -[AppController trashMediaCache:] + 435 (Housekeeper) [0x100010e7a] 
      13 +[MYFileManager trashFilesOfType:inFolder:] + 482 (Housekeeper) [0x100022e2a] 
      13 +[MYFileManager trashFile:] + 22 (Housekeeper) [0x1000227f7] 
       12 +[MYFileManager trashFile:shouldAuth:] + 226 (Housekeeper) [0x1000228de] 
       12 -[NSWorkspace performFileOperation:source:destination:files:tag:] + 319 (AppKit) [0x7fff8aa72bbb] 
        12 -[NSWorkspace _fileOperation:source:destination:files:] + 917 (AppKit) [0x7fff8aa72f7e] 
        12 _FSOperateOnObjectSync + 482 (CarbonCore) [0x7fff87ab309c] 
         12 _NodeOperation + 488 (DesktopServicesPriv) [0x7fff90d6e38a] 
         4 TFSCopyOperation::DoMoveToTrash(TCountedPtr<TCFURLInfo> const&) + 330 (DesktopServicesPriv) [0x7fff90d7e28c] 
          4 TFSInfo::MoveAndRenameTo(TCountedPtr<TFSInfo> const&, TUString*, TCountedPtr<TFSInfo>&) const + 677 (DesktopServicesPriv) [0x7fff90da4ae7] 
          4 TCFURLInfo::RenameWithoutReplacing(char const*, char const*, bool) + 162 (DesktopServicesPriv) [0x7fff90d89620] 
           4 __rename + 10 (libsystem_kernel.dylib) [0x7fff861ba97a] 
           3 <Suppressed> 
         3 TFSCopyOperation::DoMoveToTrash(TCountedPtr<TCFURLInfo> const&) + 1033 (DesktopServicesPriv) [0x7fff90d7e54b] 
          3 THFSPlusPropertyStore::SetProperty(TUString const&, unsigned int, TPropertyReference const&) + 81 (DesktopServicesPriv) [0x7fff90d26bc1] 
          3 TDSMutex::Acquire() + 34 (DesktopServicesPriv) [0x7fff90ce5d00] 
           3 __psynch_mutexwait + 10 (libsystem_kernel.dylib) [0x7fff861ba746] 
           1 <Suppressed> 
         2 TFSCopyOperation::DoMoveToTrash(TCountedPtr<TCFURLInfo> const&) + 995 (DesktopServicesPriv) [0x7fff90d7e525] 
          2 THFSPlusPropertyStore::SetProperty(TUString const&, unsigned int, TPropertyReference const&) + 81 (DesktopServicesPriv) [0x7fff90d26bc1] 
          2 TDSMutex::Acquire() + 34 (DesktopServicesPriv) [0x7fff90ce5d00] 
           2 __psynch_mutexwait + 10 (libsystem_kernel.dylib) [0x7fff861ba746] 
           1 <Suppressed> 

Как видно из журнала, startClean выполняется на главной нить. Но запутанная часть является то, что есть только один вызов startClean, следующий образом:

[NSThread detachNewThreadSelector:@selector(startClean) toTarget:self withObject:nil]; 

Таким образом, код должен быть выполнение в отдельном потоке, и на самом деле, это так, как это работает на моей системе, но больше один клиент испытал это на OS X 10.9.5. Есть несколько вызовов основного потока внутри startClean, но они предназначены только для обновления пользовательского интерфейса. Вызов trashMediaCache выполняется командой performSelector: withObject: но не выполняетSelectorOnMainThread.

Кто-нибудь видел это раньше? Является ли это ошибкой OS X или существуют ситуации, когда система будет перенаправлять вызовы в основной поток по дизайну? Или я просто неправильно интерпретирую журнал?

P.S. Я знаю, что могу использовать диспетчерский вызов или операционную очередь, и это может решить проблему, но я все равно хотел бы узнать ответ на исходный вопрос.

ответ

1

Очевидно, что ваш метод startClean, который работает в фоновом режиме, запускает некоторый код для запуска в основном потоке, что вызывает тупик.
Одна из возможностей заключается в том, что startClean использует Основные данные. Это описано here.
Другая возможность - обработчик завершения, который выполняется на основном потоке. Есть много, например. MKLocalSearchCompletionHandler, где документы явно указывают, что они всегда выполняются в основном потоке.

+0

Я прошел через свой собственный код, и я уверен, что в основной поток ничего не происходит, поэтому похоже, что это скорее всего происходит в коде Apple. Я, наверное, никогда не дойду до конца. – mwoods

1

__NSThread__main__ не является основной нитью. Это внутренняя точка входа для выполнения NSThread.

+0

А, я думаю, ты прав. Я просто получил отчет о зависании из другого приложения, а стек вызовов начал с 'main' вместо' __NSThread__main__'. – mwoods

Смежные вопросы