Note on Carbon Sparkle Crashes
I've recently been using Sparkle For Carbon, which is really great except for the way that it crashes all the time. Without debug information from the Sparkle framework the crashes generate stack traces like this:
Wed Jan 5 12:31:31 Niobium-II.local 3D BoA Editor[7224] <Error>: kCGErrorIllegalArgument: CGSGetWindowTags: Invalid window 0x4f5
Program received signal: “EXC_BAD_ACCESS”
#0 0x9577fed7 in objc_msgSend
#1 0x00386b40 in ??
#2 0x001ce506 in load_dsa_key
#3 0x001cf97e in load_dsa_key
#4 0x001d05da in load_dsa_key
#5 0x001c764d in dyld_stub_strtol
#6 0x9910bc46 in -[NSApplication sendAction:to:from:]
#7 0x991eb465 in -[NSControl sendAction:to:]
#8 0x991e6f12 in -[NSCell _sendActionFrom:]
#9 0x991e6209 in -[NSCell trackMouse:inRect:ofView:untilMouseUp:]
#10 0x9923b8a1 in -[NSButtonCell trackMouse:inRect:ofView:untilMouseUp:]
#11 0x991e4c5f in -[NSControl mouseDown:]
#12 0x991e2c68 in -[NSWindow sendEvent:]
#13 0x997560ca in carbonAppWindowMouseHandler
#14 0x997574a0 in carbonAppWindowHandler
#15 0x909caf2f in DispatchEventToHandlers
#16 0x909ca1f6 in SendEventToEventTargetInternal
#17 0x909ec9bb in SendEventToEventTarget
#18 0x909fe4db in ToolboxEventDispatcherHandler
#19 0x909cb380 in DispatchEventToHandlers
#20 0x909ca1f6 in SendEventToEventTargetInternal
#21 0x909ec9bb in SendEventToEventTarget
#22 0x90b75cc3 in ToolboxEventDispatcher
#23 0x90b7f981 in GetOrPeekEvent
#24 0x90b7fb85 in GetNextEventMatchingMask
#25 0x90b7fe42 in WNEInternal
#26 0x90b7ffed in WaitNextEvent
#27 0x00007b81 in Handle_One_Event at Bl A Editor.cpp:406
#28 0x000084e0 in main at Bl A Editor.cpp:289
As pointed out during this discussion (See this post), most of the top of that trace is completely bogus. With debug information, a picture closer to reality emerges:
Exception Type: EXC_BAD_ACCESS (SIGBUS)
Exception Codes: KERN_PROTECTION_FAILURE at 0x0000000000000000
Crashed Thread: 0 Dispatch queue: com.apple.main-thread
Application Specific Information:
objc_msgSend() selector name: delegate
Thread 0 Crashed: Dispatch queue: com.apple.main-thread
0 libobjc.A.dylib 0x9577fedb objc_msgSend + 27
1 org.andymatuschak.Sparkle 0x001d1996 -[SUBasicUpdateDriver abortUpdate] + 113 (SUBasicUpdateDriver.m:295)
2 org.andymatuschak.Sparkle 0x001d328f -[SUUIBasedUpdateDriver abortUpdate] + 120 (SUUIBasedUpdateDriver.m:170)
3 org.andymatuschak.Sparkle 0x001d37bc -[SUScheduledUpdateDriver didNotFindUpdate] + 36 (SUScheduledUpdateDriver.m:23)
4 org.andymatuschak.Sparkle 0x001d007c -[SUBasicUpdateDriver appcastDidFinishLoading:] + 568 (SUBasicUpdateDriver.m:108)
5 org.andymatuschak.Sparkle 0x001c859e -[SUAppcast connectionDidFinishLoading:] + 2151 (SUAppcast.m:165)
6 com.apple.Foundation 0x96dbf56b -[NSURLConnection(NSURLConnectionReallyInternal) sendDidFinishLoading] + 84
7 com.apple.Foundation 0x96dbf4dc _NSURLConnectionDidFinishLoading + 133
8 com.apple.CFNetwork 0x94b0144b URLConnectionClient::_clientDidFinishLoading(URLConnectionClient::ClientConnectionEventQueue*) + 197
9 com.apple.CFNetwork 0x94b78b88 URLConnectionClient::ClientConnectionEventQueue::processAllEventsAndConsumePayload(XConnectionEventInfo<XClientEvent, XClientEventParams>*, long) + 306
10 com.apple.CFNetwork 0x94b78e52 URLConnectionClient::ClientConnectionEventQueue::processAllEventsAndConsumePayload(XConnectionEventInfo<XClientEvent, XClientEventParams>*, long) + 1020
11 com.apple.CFNetwork 0x94af3ab0 URLConnectionClient::processEvents() + 94
12 com.apple.CFNetwork 0x94af3953 MultiplexerSource::perform() + 183
13 com.apple.CoreFoundation 0x9439c4cb __CFRunLoopDoSources0 + 1563
14 com.apple.CoreFoundation 0x94399f8f __CFRunLoopRun + 1071
15 com.apple.CoreFoundation 0x94399464 CFRunLoopRunSpecific + 452
16 com.apple.CoreFoundation 0x94399291 CFRunLoopRunInMode + 97
17 com.apple.HIToolbox 0x909f7f9c RunCurrentEventLoopInMode + 392
18 com.apple.HIToolbox 0x90b7fc8c GetNextEventMatchingMask + 453
19 com.apple.HIToolbox 0x90b7fe42 WNEInternal + 160
20 com.apple.HIToolbox 0x90b7ffed WaitNextEvent + 57
21 com.spidweb.BoA3DEditor 0x0000826d Handle_One_Event() + 66 (Bl A Editor.cpp:414)
22 com.spidweb.BoA3DEditor 0x00008bcc main + 501 (Bl A Editor.cpp:292)
23 com.spidweb.BoA3DEditor 0x00005027 _start + 209
24 com.spidweb.BoA3DEditor 0x00004f55 start + 41
Closer investigation reveals that the crash actually happens in SUUpdateDriver::abortUpdate:
- (void)abortUpdate
{
[self setValue:[NSNumber numberWithBool:YES] forKey:@"finished"];
[[NSNotificationCenter defaultCenter] postNotificationName:SUUpdateDriverFinishedNotification object:self];
if ([[updater delegate] respondsToSelector:@selector(updaterDidAbandonUpdate:)])
[[updater delegate] updaterDidAbandonUpdate:updater];
}
Given the information which went with the stack trace, it looks suspiciously like this fails because updater is nil, so I added a check for that, and also a check for [updater delegate] being nil, although I think respondsToSelector might take care of that anyway. The result was simply:
- (void)abortUpdate
{
[self setValue:[NSNumber numberWithBool:YES] forKey:@"finished"];
[[NSNotificationCenter defaultCenter] postNotificationName:SUUpdateDriverFinishedNotification object:self];
if(updater!=nil && [updater delegate]!=nil && [[updater delegate] respondsToSelector:@selector(updaterDidAbandonUpdate:)])
[[updater delegate] updaterDidAbandonUpdate:updater];
}
This still does not work, for reasons which are not clear to me. After a little more digging and some use of printf, I learned that [updater delegate] was in fact nil, and I even made it point to something valid1 but nothing changed. I wondered if perhaps this was a use-after-free problem, so I changed SUUpdateDriver to retain updater, but this also had no impact.
In the end, the only thing I've found which works is to remove the latter two lines of code from abortUpdate2, which works for me since I wasn't using the kHICommandSparkleDownloadAbandoned which should have been generated (as best I can tell), but as solutions go, this one is not very satisfactory, since I never really did understand the problem.