iOS 应用程序中 _class_initialize 中的 semaphore_wait_signal_trap 死锁
我的一个实体托管对象需要设置一个仅运行时的树状结构,其中节点是 NSObject 的子类(它们不是托管对象)。
我在两个地方设置了该结构(从而分配了一堆这些节点):
- 当创建一个新的此类托管对象时:一切正常。
- 当读回现有的托管对象时,在其
awakeFromFetch
方法中。
这就是我遇到问题的地方:对 Node *newNode = [Node alloc]; 的调用永远不会返回。我可以使用调试器中断,并且代码卡在 semaphore_wait_signal_trap 中。这是完整的调用堆栈:
#0 0x937ac0e2 in semaphore_wait_signal_trap ()
#1 0x937b1be6 in pthread_mutex_lock ()
#2 0x01881c73 in _class_initialize ()
#3 0x0188973f in prepareForMethodLookup ()
#4 0x01880069 in lookUpMethod ()
#5 0x018801d6 in _class_lookupMethodAndLoadCache ()
#6 0x018930e3 in objc_msgSend ()
#7 0x000957d8 in -[MyEntity awakeFromFetch] at MyEntity:114
所以看来我的 Node 类无法初始化。事实上,这是本次会议中第一次使用 Node 类。为了检查这一点,我在应用程序启动时插入了单个 Node
的虚假分配。即调用成功,现在上述问题消失了。
但是,我不满意,有两个原因:
1-我仍然不明白为什么在 awakeFromFetch
中第一次分配 Node
失败。如果我不明白错误发生的原因以及为什么修复是实际的修复,我不会认为错误已修复。
2- 现在,当第一次使用另一个类时,应用程序会稍晚崩溃,这次不是在任何awakeFromFetch
中。
很明显,我的问题与 awakeFromFetch 或 Core Data 无关。不知何故,我的 Objective-C 运行时行为异常,我不知道为什么。
简单的问题:什么会导致 _class_initialize
导致 p 线程死锁?
事实上,谷歌搜索 semaphore_wait_signal_trap 会产生很多结果,全部与 pthreads 相关,很少与 iOS/Objective-C/Cocoa 相关。
请注意,我在这里根本不使用线程。
我很困惑。知道如何调试这个吗?
编辑:永远不会返回的源代码行是:
Node *newNode = [[Node alloc] init];
为了找出发生了什么,我将其分成两部分:
Node *newNode = [Node alloc];
newNode = [newNode init];
问题发生在这两行中的第一行。
One of my entity managed objects need to setup a runtime-only tree-like structure where nodes are subclasses of NSObject
(they are not managed object).
I setup that structure (and thus allocates a bunch of those nodes) in two places:
- when creating a new such managed object: everything is working fine.
- when reading back an existing managed object, in its
awakeFromFetch
method.
That's where I have my problem: the call to Node *newNode = [Node alloc];
never returns. I can break using the debugger, and the code is stuck in semaphore_wait_signal_trap
. Here is the full call stack:
#0 0x937ac0e2 in semaphore_wait_signal_trap ()
#1 0x937b1be6 in pthread_mutex_lock ()
#2 0x01881c73 in _class_initialize ()
#3 0x0188973f in prepareForMethodLookup ()
#4 0x01880069 in lookUpMethod ()
#5 0x018801d6 in _class_lookupMethodAndLoadCache ()
#6 0x018930e3 in objc_msgSend ()
#7 0x000957d8 in -[MyEntity awakeFromFetch] at MyEntity:114
So it seems my Node class fails to initialize. Indeed, this is the very first use of the Node class in this session. To check that, I inserted a spurious allocation of a single Node
at application startup time. That calls succeeds, and now the above problem disappears.
However, I am not satisfied, for two reasons:
1- I still don't understand why allocating a Node
for the first time in awakeFromFetch
fails. And I don't consider a bug fixed if I don't understand why it occurred and why the fix is an actual fix.
2- The application now crashes slightly later when using another class for the first time, this time not in any awakeFromFetch
.
So clearly my problem is not related to awakeFromFetch
nor Core Data. Somehow, my Objective-C runtime is misbehaving, I don't know why.
Simple question: what could lead _class_initialize
to p-thread deadlock?
Indeed googling for semaphore_wait_signal_trap
yields many hits, all related to pthreads, few related to iOS/Objective-C/Cocoa.
Note that I don't use threads at all here.
I'm puzzled. Any idea how to debug this?
Edit: the source line that never returns was:
Node *newNode = [[Node alloc] init];
To find out what's going on, I split it in two:
Node *newNode = [Node alloc];
newNode = [newNode init];
The problems occurs on the first of those two lines.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
Apple关于-[NSManagedObject awakeFromFetch] 说:
你这样做了吗?
然而,即使这解决了你的问题,我也不知道为什么;)
Apple's document about -[NSManagedObject awakeFromFetch] said that:
Did you do that?
However, even if this solve your problem, I don't know why ;)
好吧,我清理了所有目标,然后重建了。没有任何改善。
然后我删除了 Xcode 的 Derived Data 目录,你瞧,问题就消失了。
合理的结论是假设 Xcode 4 中存在一些故障。
我什至不会尝试解释所有损失的时间。
Well, I cleaned all my targets, and rebuilt. No improvement.
Then I deleted Xcode's Derived Data directory, and lo and behold, the problem went away.
The reasonable conclusion is to assume some glitch/but in Xcode 4.
I will not even try to account for all the lost hours.