quicksilver/Quicksilver — pull request #943 by pjrobertson (2012-06-16 12:13:27+00:00)
Title: ß69: Crash fixes

The first commit attempts to stop any array from being mutated whilst it is being written to disk. As I do not experience the crash, I cannot comment on whether it has fixed the problem - it appears to be a multithreading issue. If anybody has any other suggestions (I'm 90% sure that this, along with the @ synchronise call I made previously) will fix any crashes here.
The crash log for this crash:

Process: Quicksilver [64198]
Path: /Users/Shared/Applications/Quicksilver.app/Contents/MacOS/Quicksilver
Identifier: com.blacktree.Quicksilver
Version: ß69 (3929)
Code Type: X86-64 (Native)
Parent Process: ??? [1]

Date/Time: 2012-06-13 00:21:07.100 -0700
OS Version: Mac OS X 10.6.8 (10K549)
Report Version: 6

Exception Type: EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Crashed Thread: 9

Application Specific Information:
abort() called
*** Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection was mutated while being enumerated.{type = mutable dict, count = 2,
entries =>
0 : {contents = "qs.process"} = {type = mutable dict, count = 24,
entries =>
1 : {contents = "CFBundleName"} = {contents = "RockMelt Helper"}
2 : {contents = "BundlePath"} = {contents = "USER_DIR/Applications/RockMelt.app/Contents/Versions/0.16.91.468/RockMelt Helper.app"}
5 : {contents = "NSApplicationProcessIdentifier"} = {value = +63144, type = kCFNumberSInt32Type}
6 : {contents = "NSApplicationName"} = {contents = "RockMelt Helper"}
7 : {contents = "IsCheckedInAttr"} = {value = true}
8 : {contents = "ParentPSN"} = {value = +33341386, type = kCFNumberSInt64Type}
9 : {contents = "NSApplicationProcessSerialNumberHigh"} = {value = +0, type = kCFNumberSInt32Type}
11 : {contents = "Attributes"} = {value = +69632, type = kCFNumberSInt64Type}
12 : {contents = "LSSystemWillDisplayDeathNotification"} = {value = false}
13 : {contents = "CFBundleVersion"} = {value = +0, type = kCFNumberSInt32Type}
15 : {contents = "NSApplicationProcessSerialNumberLow"} = {value = +34160786, type = kCFNumberSInt64Type}
17 : {contents = "FileType"} = {contents = "APPL"}
19 : {contents = "NSApplicationBundleIdentifier"} = {contents = "com.rockmelt.RockMelt.helper"}
21 : {contents = "LSUIPresentationMode"} = {value = +0, type = kCFNumberSInt32Type}
24 : {contents = "CFBundleExecutable"} = {contents = "USER_DIR/Applications/RockMelt.app/Contents/Versions/0.16.91.468/RockMelt Helper.app/Contents/MacOS/RockMelt Helper"}
25 : {contents = "FileCreator"} = {contents = "????"}
26 : {contents = "NSApplicationPath"} = {contents = "USER_DIR/Applications/RockMelt.app/Contents/Versions/0.16.91.468/RockMelt Helper.app"}
28 : {contents = "CFBundleIdentifier"} = {contents = "com.rockmelt.RockMelt.helper"}
29 : {contents = "LSBackgroundOnly"} = {value = false}
31 : {contents = "Flavor"} = {value = +2, type = kCFNumberSInt32Type}
34 : {contents = "pid"} = {value = +63144, type = kCFNumberSInt32Type}
35 : {contents = "LSCheckInTime*"} = 2012-06-13 00:08:14 -0700
38 : {contents = "PSN"} = {value = +34160786, type = kCFNumberSInt64Type}
40 : {contents = "LSUIElement"} = {value = true}
}

1 : {contents = "NSFilenamesPboardType"} = USER_DIR/Applications/RockMelt.app/Contents/Versions/0.16.91.468/RockMelt Helper.app
}
'
*** Call stack at first throw:
(
0 CoreFoundation 0x00007fff8689e784 __exceptionPreprocess + 180
1 libobjc.A.dylib 0x00007fff86e1df03 objc_exception_throw + 45
2 CoreFoundation 0x00007fff868f65bf __NSFastEnumerationMutationHandler + 303
3 CoreFoundation 0x00007fff8684c54e -[__NSFastEnumerationEnumerator nextObject] + 78
4 Foundation 0x00007fff80b84699 _NSIsPList + 511
5 Foundation 0x00007fff80b84671 _NSIsPList + 471
6 Foundation 0x00007fff80b845c7 _NSIsPList + 301
7 Foundation 0x00007fff80c0ff6f -[NSArray(NSArray) writeToFile:atomically:] + 68
8 QSCore 0x00000001000d889d -[QSCatalogEntry saveIndex] + 225
)

CUTTING OUT UNIMPORTANT STUFF

Thread 9 Crashed:
0 libSystem.B.dylib	0x00007fff872d3395 usleep$NOCANCEL + 0
1 libSystem.B.dylib	0x00007fff872f2a00 abort + 93
2 libstdc++.6.dylib	0x00007fff8243b5d2 __tcf_0 + 0
3 libobjc.A.dylib	0x00007fff86e21b39 _objc_terminate + 100
4 libstdc++.6.dylib	0x00007fff82439ae1 __cxxabiv1::__terminate(void (*)()) + 11
5 libstdc++.6.dylib	0x00007fff82439b16 __cxxabiv1::__unexpected(void (*)()) + 0
6 libstdc++.6.dylib	0x00007fff82439bfc __gxx_exception_cleanup(_Unwind_Reason_Code, _Unwind_Exception*) + 0
7 libobjc.A.dylib	0x00007fff86e1dfa2 object_getIvar + 0
8 com.apple.CoreFoundation	0x00007fff868f65bf __NSFastEnumerationMutationHandler + 303
9 com.apple.CoreFoundation	0x00007fff8684c54e -[__NSFastEnumerationEnumerator nextObject] + 78
10 com.apple.Foundation	0x00007fff80b84699 _NSIsPList + 511
11 com.apple.Foundation	0x00007fff80b84671 _NSIsPList + 471
12 com.apple.Foundation	0x00007fff80b845c7 _NSIsPList + 301
13 com.apple.Foundation	0x00007fff80c0ff6f -[NSArray(NSArray) writeToFile:atomically:] + 68
14 com.blacktree.QSCore	0x00000001000d889d -[QSCatalogEntry saveIndex] + 225
15 com.blacktree.QSCore	0x00000001000d8d07 -[QSCatalogEntry scanAndCache] + 219
16 com.blacktree.QSCore	0x00000001000d90e9 -[QSCatalogEntry scanForced:] + 683
17 com.blacktree.QSCore	0x00000001000e1589 -[QSLibrarian scanCatalogIgnoringIndexes:] + 458
18 com.apple.Foundation	0x00007fff80b7d114 __NSThread__main__ + 1429
19 libSystem.B.dylib	0x00007fff8723cfd6 _pthread_start + 331
20 libSystem.B.dylib	0x00007fff8723ce89 thread_start + 13

The second commit fixes a crash if the `downloadsURL` doesn't exist (latest download proxy). Passing a `nil` to `contentsOfDirectory` causes a crash, so I've just put an `if()` in there.
Alongside this, I took the liberty of getting the user's preferred downloads folder (from Safari's prefs) as opposed to just assuming `~/Downloads`. In most cases, it will probably resolve to the same thing. The crash that this fixes:

Process: Quicksilver [85006]
Path: /Applications/Quicksilver.app/Contents/MacOS/Quicksilver
Identifier: com.blacktree.Quicksilver
Version: ß69 (3929)
Code Type: X86-64 (Native)
Parent Process: launchd [389]

Date/Time: 2012-06-16 01:06:10.568 +0200
OS Version: Mac OS X 10.7.4 (11E53)
Report Version: 9

Crashed Thread: 14

Exception Type: EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000

Application Specific Information:
objc[85006]: garbage collection is OFF
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSFileManager contentsOfDirectoryAtURL:includingPropertiesForKeys:options:error:]: URL is nil'
*** First throw call stack:
(
0 CoreFoundation 0x00007fff8f8ccf56 __exceptionPreprocess + 198
1 libobjc.A.dylib 0x00007fff89caad5e objc_exception_throw + 43
2 CoreFoundation 0x00007fff8f8ccd8a +[NSException raise:format:arguments:] + 106
3 CoreFoundation 0x00007fff8f8ccd14 +[NSException raise:format:] + 116
4 Foundation 0x00007fff8fa5bbb6 -[NSFileManager contentsOfDirectoryAtURL:includingPropertiesForKeys:options:error:] + 108
5 QSCore 0x0000000100101fc0 -[QSDownloads resolveProxyObject:] + 243
)

terminate called throwing an exception
abort() called

Thread 0:: Dispatch queue: com.apple.main-thread
0 libsystem_kernel.dylib	0x00007fff93f71af2 read + 10
1 com.apple.Foundation	0x00007fff8fa0eed1 _NSReadBytesFromFileWithExtendedAttributes + 878
2 com.apple.Foundation	0x00007fff8fa0eb5a _NSReadBytesFromFile + 47
3 com.apple.Foundation	0x00007fff8fa25546 -[NSData(NSData) initWithContentsOfFile:options:error:] + 193
4 com.apple.Foundation	0x00007fff8fa8cb48 -[NSData(NSData) initWithContentsOfURL:options:error:] + 238
5 com.apple.AppKit	0x00007fff8c985387 NSImageRepNewDataFromFileURL + 247
6 com.apple.AppKit	0x00007fff8c5b70fc +[NSImageRep _imageRepsWithContentsOfURL:expandImageContentNow:giveUpOnNetworkURLsWithoutGoodExtensions:] + 548
7 com.apple.AppKit	0x00007fff8c5b6e9a __-[NSImageURLReferencingRepProvider representations]_block_invoke_1 + 48
8 com.apple.Foundation	0x00007fff8fa3d347 _NSFaultInObject + 35
9 com.apple.AppKit	0x00007fff8c587ae7 -[NSImageURLReferencingRepProvider representations] + 80
10 com.apple.AppKit	0x00007fff8c542891 __-[NSImage _usingRepresentationsPerformBlock:]_block_invoke_1 + 83
11 com.apple.AppKit	0x00007fff8c542825 -[NSImage _usingRepProviderPerformBlock:] + 37
12 com.apple.AppKit	0x00007fff8c5427fa -[NSImage _usingRepresentationsPerformBlock:] + 75
13 com.apple.AppKit	0x00007fff8c587a4a -[NSImage representations] + 136
14 com.blacktree.QSFoundation	0x000000010005b1ad -[NSImage(Scaling) representationOfSize:] + 38
15 com.blacktree.QSCore	0x00000001000fd0c1 -[QSResourceManager imageNamed:inBundle:] + 936
16 com.blacktree.QSCore	0x00000001000e6fcd -[QSFileSystemObjectHandler setQuickIconForObject:] + 256
17 com.blacktree.QSCore	0x00000001000e6552 -[QSObject(Icon) icon] + 422
18 com.apple.CoreFoundation	0x00007fff8f8beefc __invoking___ + 140
19 com.apple.CoreFoundation	0x00007fff8f8bed94 -[NSInvocation invoke] + 132
20 com.apple.CoreFoundation	0x00007fff8f8bef64 -[NSInvocation invokeWithTarget:] + 52
21 com.apple.CoreFoundation	0x00007fff8f8b9fa4 ___forwarding___ + 756
22 com.apple.CoreFoundation	0x00007fff8f8b9c38 _CF_forwarding_prep_0 + 232
23 com.blacktree.QSInterface	0x000000010016eab2 -[QSObjectCell drawObjectImage:inRect:cellFrame:controlView:flipped:opacity:] + 46
24 com.blacktree.QSInterface	0x000000010016ded0 -[QSObjectCell drawIconForObject:withFrame:inView:] + 427
25 com.blacktree.QSInterface	0x000000010016dce2 -[QSObjectCell drawInteriorWithFrame:inView:] + 198
26 com.blacktree.QSInterface	0x000000010016d420 -[QSObjectCell drawWithFrame:inView:] + 977
27 com.apple.AppKit	0x00007fff8c61ac88 -[NSTableView drawRow:clipRect:] + 1647
28 com.blacktree.QSInterface	0x000000010017cea0 -[QSTableView drawRow:clipRect:] + 351
29 com.apple.AppKit	0x00007fff8c61a465 -[NSTableView drawRowIndexes:clipRect:] + 565
30 com.apple.AppKit	0x00007fff8c618587 -[NSTableView drawRect:] + 1390
31 com.apple.AppKit	0x00007fff8c58097a -[NSView _drawRect:clip:] + 3758
32 com.apple.AppKit	0x00007fff8c5adb4f -[NSView _recursiveDisplayAllDirtyWithLockFocus:visRect:] + 1583
33 com.apple.AppKit	0x00007fff8c5adf7b -[NSView _recursiveDisplayAllDirtyWithLockFocus:visRect:] + 2651
34 com.apple.AppKit	0x00007fff8c57df55 -[NSView _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:] + 1032
35 com.apple.AppKit	0x00007fff8c57f20a -[NSView _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:] + 5821
36 com.apple.AppKit	0x00007fff8c57f20a -[NSView _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:] + 5821
37 com.apple.AppKit	0x00007fff8c57f20a -[NSView _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:] + 5821
38 com.apple.AppKit	0x00007fff8c6ca560 -[NSNextStepFrame _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:] + 274
39 com.apple.AppKit	0x00007fff8c57886f -[NSView _displayRectIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:] + 4755
40 com.apple.AppKit	0x00007fff8c5712ed -[NSView displayIfNeeded] + 1676
41 com.apple.AppKit	0x00007fff8c6ca438 -[NSNextStepFrame displayIfNeeded] + 83
42 com.apple.AppKit	0x00007fff8c570a2d _handleWindowNeedsDisplayOrLayoutOrUpdateConstraints + 648
43 com.apple.CoreFoundation	0x00007fff8f88c8e7 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
44 com.apple.CoreFoundation	0x00007fff8f88c846 __CFRunLoopDoObservers + 374
45 com.apple.CoreFoundation	0x00007fff8f861af9 __CFRunLoopRun + 825
46 com.apple.CoreFoundation	0x00007fff8f861486 CFRunLoopRunSpecific + 230
47 com.apple.HIToolbox	0x00007fff8d67e4d3 RunCurrentEventLoopInMode + 277
48 com.apple.HIToolbox	0x00007fff8d685781 ReceiveNextEventCommon + 355
49 com.apple.HIToolbox	0x00007fff8d68560e BlockUntilNextEventMatchingListInMode + 62
50 com.apple.AppKit	0x00007fff8c534e31 _DPSNextEvent + 659
51 com.apple.AppKit	0x00007fff8c534735 -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 135
52 com.apple.AppKit	0x00007fff8c531071 -[NSApplication run] + 470
53 com.apple.AppKit	0x00007fff8c7ad244 NSApplicationMain + 867
54 com.blacktree.Quicksilver	0x0000000100001f70 0x100000000 + 8048

Thread 14 Crashed:
0 libsystem_kernel.dylib	0x00007fff93f70ce2 __pthread_kill + 10
1 libsystem_c.dylib	0x00007fff94af67d2 pthread_kill + 95
2 libsystem_c.dylib	0x00007fff94ae7a7a abort + 143
3 libc++abi.dylib	0x00007fff8aa787bc abort_message + 214
4 libc++abi.dylib	0x00007fff8aa75fcf default_terminate() + 28
5 libobjc.A.dylib	0x00007fff89cab1b9 _objc_terminate + 94
6 libc++abi.dylib	0x00007fff8aa76001 safe_handler_caller(void (*)()) + 11
7 libc++abi.dylib	0x00007fff8aa7605c std::terminate() + 16
8 libc++abi.dylib	0x00007fff8aa77152 __cxa_throw + 114
9 libobjc.A.dylib	0x00007fff89caae7a objc_exception_throw + 327
10 com.apple.CoreFoundation	0x00007fff8f8ccd8a +[NSException raise:format:arguments:] + 106
11 com.apple.CoreFoundation	0x00007fff8f8ccd14 +[NSException raise:format:] + 116
12 com.apple.Foundation	0x00007fff8fa5bbb6 -[NSFileManager contentsOfDirectoryAtURL:includingPropertiesForKeys:options:error:] + 108
13 com.blacktree.QSCore	0x0000000100101fc0 -[QSDownloads resolveProxyObject:] + 243
14 com.blacktree.QSCore	0x00000001000f9dec -[QSProxyObject proxyObject] + 75
15 com.blacktree.QSCore	0x00000001000e615f -[QSObject(Icon) loadIcon] + 247
16 com.apple.CoreFoundation	0x00007fff8f8beefc __invoking___ + 140
17 com.apple.CoreFoundation	0x00007fff8f8bed94 -[NSInvocation invoke] + 132
18 com.apple.CoreFoundation	0x00007fff8f8bef64 -[NSInvocation invokeWithTarget:] + 52
19 com.apple.CoreFoundation	0x00007fff8f8b9fa4 ___forwarding___ + 756
20 com.apple.CoreFoundation	0x00007fff8f8b9c38 _CF_forwarding_prep_0 + 232
21 com.blacktree.QSCore	0x00000001000de6a5 -[QSIconLoader loadIcons] + 300
22 com.apple.Foundation	0x00007fff8fa5a72a -[NSThread main] + 68
23 com.apple.Foundation	0x00007fff8fa5a6a2 __NSThread__main__ + 1575
24 libsystem_c.dylib	0x00007fff94af48bf _pthread_start + 335
25 libsystem_c.dylib	0x00007fff94af7b75 thread_start + 13