numist / Switch

A window-based context switcher for the Mac
157 stars 17 forks source link

Crash in `- [SWWindowContentsService _windowUpdateNotification:]` #96

Closed numist closed 3 years ago

numist commented 10 years ago

Reported by @bavarious, who adds that DictationIM crashes shortly after Switch. Both are Accessibility applications, but it may be a red herring since Switch is crashing in code unrelated to the Accessibility APIs. I suspect that Switch crashing may have left AX in a bad enough mood to take it out on others.

From the report:

I believe the problem happened after I typed ↑ whilst the context switcher was visible.

Unable to reproduce locally; maybe something else on the system was bound to ⌥↑?

From the crash group:

Thread 9 Crashed:
0   libobjc.A.dylib                      0x00007fff8375d7a2 objc_retain + 18
1   Switch                               0x00000001032d74c6 __53-[SWWindowContentsService _windowUpdateNotification:]_block_invoke (SWWindowContentsService.m:169)
2   libdispatch.dylib                    0x00007fff823a21bb _dispatch_call_block_and_release + 12
3   libdispatch.dylib                    0x00007fff8239f28d _dispatch_client_callout + 8
4   libdispatch.dylib                    0x00007fff823a1673 _dispatch_queue_drain + 451
5   libdispatch.dylib                    0x00007fff823a29c1 _dispatch_queue_invoke + 110
6   libdispatch.dylib                    0x00007fff823a0f87 _dispatch_root_queue_drain + 75
7   libdispatch.dylib                    0x00007fff823a2177 _dispatch_worker_thread2 + 40
8   libsystem_pthread.dylib              0x00007fff833d2ef8 _pthread_wqthread + 314
9   libsystem_pthread.dylib              0x00007fff833d5fb9 start_wqthread + 13

-Os seems to have collapsed some of the stack frames, but that code is dispatching windowContentService:updatedContent:forWindow: to all of the window content service's subscribers. Not sure which pointer was bad when objc_retain got to it, but it looks like a dead object problem.

This crash happened at least twice in less than an hour for one person, so it appears to be reproducible when conditions are right.

numist commented 10 years ago

Sounds like this isn't as reproducible as I'd hoped. Multi-dispatch hasn't been without its problems (https://github.com/numist/Switch/issues/65 and https://github.com/numist/NNKit/pull/9 come immediately to mind) so it's not unreasonable to expect that there's still some way for an object to slip through the cracks.

numist commented 10 years ago

But if there is, I can't find it yet.

Here's the line at 169:

[(id<SWWindowContentsSubscriber>)self.subscriberDispatcher windowContentService:self updatedContent:contentContainer.content forWindow:contentContainer.window];

The crash report adds:

Selector name found in current argument registers: subscriberDispatcher

SWWindowContentsService.m assembly from v0.0.8 when that selector is in the register bank:

mov        rsi, qword [ds:0x100031488]                           ; @selector(subscriberDispatcher)
call       r14                                                   ; imp___got__objc_msgSend (cached)
mov        rdi, rax                                              ; move result to arg1 of next call
call       imp___stubs__objc_retainAutoreleasedReturnValue       ; crash, presumably.
mov        qword [ss:rbp-0x50+var_16], rax
mov        rax, qword [ds:r13+0x28]
mov        qword [ss:rbp-0x50+var_24], rax
mov        rsi, qword [ds:0x1000315a8]                           ; subscriberDispatcher no longer in registers

subscriberDispatcher itself looks like:

push       rbp
mov        rbp, rsp
mov        rax, qword [ds:_OBJC_IVAR_$_NNService._subscriberDispatcher]
mov        rax, qword [ds:rdi+rax]
pop        rbp
ret

There's not a whole lot to go wrong here; the property is readonly and set in NNService's initializer.

numist commented 9 years ago

SWAppDelegate should implement [BITCrashManagerDelegate applicationLogForCrashManager:] to provide more context for this (and future) crashes.

numist commented 3 years ago

Obsoleted by #139, which removes the NNKit dependency.