NSThread detachNewThreadSelector在主线程上执行

时间:2014-11-13 03:56:58

标签: objective-c multithreading cocoa

少数客户使用以下挂起日志签名从我的OS X应用程序中挂起:

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中有几个对主线程的调用,但这些只是用于更新UI。 trashMediaCache调用由performSelector执行:withObject:但不执行performSelectorOnMainThread。

有没有人见过这个?这是OS X错误还是存在系统会根据设计将调用转移到主线程的情况?或者我只是误解了日志?

P.S。我知道我可以使用调度调用或操作队列,这可能会解决问题,但我仍然想知道原始问题的答案。

2 个答案:

答案 0 :(得分:1)

显然,在后台运行的startClean方法会触发一些代码在主线程上运行,从而导致死锁。
一种可能性是startClean使用核心数据。这被描述为here 另一种可能性是在主线程上执行的完成处理程序。有很多,例如MKLocalSearchCompletionHandler,文档明确声明它们总是在主线程上执行。

答案 1 :(得分:1)

__NSThread__main__不是主线索。它是NSThread执行的内部入口点。