NSTextView inspector bar crash on Sierra 10.12 - cocoa

Is anyone else seeing a crash calling setUsesInspectorBar on NSTextView for Sierra (release build)? This code worked just fine on 10.11.5 but crashes in AppKit on Sierra. I thought it was a beta version bug I'm still getting it on the full release.
Here's the back trace from lldb.
(lldb) bt
* thread #1: tid = 0x76deb, 0x9ecfe013 libobjc.A.dylib`objc_msgSend + 19, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0xa007cc0f)
* frame #0: 0x9ecfe013 libobjc.A.dylib`objc_msgSend + 19
frame #1: 0x95c5f861 Foundation`releasingRelinquish + 29
frame #2: 0x95c22636 Foundation`-[NSConcreteMapTable removeObjectForKey:] + 127
frame #3: 0x92fbec6e AppKit`-[NSStackViewContainer removeView:] + 102
frame #4: 0x92798554 AppKit`-[NSStackView _insertView:atIndex:inGravity:animated:] + 212
frame #5: 0x9279847b AppKit`-[NSStackView insertView:atIndex:inGravity:] + 40
frame #6: 0x9279839b AppKit`-[NSStackView addView:inGravity:] + 78
frame #7: 0x92f5ec2c AppKit`-[__NSInspectorBarView addItem:] + 71
frame #8: 0x929281c1 AppKit`__23-[NSInspectorBar _tile]_block_invoke + 303
frame #9: 0x94566871 CoreFoundation`__53-[__NSArrayM enumerateObjectsWithOptions:usingBlock:]_block_invoke + 81
frame #10: 0x94566717 CoreFoundation`-[__NSArrayM enumerateObjectsWithOptions:usingBlock:] + 167
frame #11: 0x945665f5 CoreFoundation`-[NSArray enumerateObjectsUsingBlock:] + 53
frame #12: 0x92925e95 AppKit`-[NSInspectorBar _tile] + 484
frame #13: 0x92924e3d AppKit`-[NSInspectorBar _update] + 224
frame #14: 0x92630b28 AppKit`-[NSTextView updateInspectorBar] + 71
frame #15: 0x9263159b AppKit`-[NSTextView updateRuler] + 2622
frame #16: 0x9292440f AppKit`-[NSTextView(NSSharing) setUsesInspectorBar:] + 350
frame #17: 0x0014eef4 DockShelf`"-[TTextEditorWindowController awakeFromNib]"(self=0x0073ecc0, _cmd="awakeFromNib") + 116 at UTextEditor_2.pas:124

This is a bug in AppKit with 32-bit apps. Unfortunately, not workaround-able (without removing inspector bar support) and will require a fix in AppKit.
This should be fixed with 10.12.2

Try to remove NSTextView component in IB and then insert it back again from component's palette. It is possible that your old XIB file contains some keywords which are not recognised/compiled properly into NIB file and Sierra cannot process file.

Related

Cocoa API keeps resetting our NSCursor

We have an application that has a full screen video player and a floating window (pallet) can be brought up to give users tools to modify the video, there is only one view for video playback and all the drawing occur in there, its an NSOpenGLView subclass. If the user click on a button in the pallet, and then move of the pallet onto the video view we use mouseEntered: to update the cursor -[NSCursor set] to one to reflect that the user is drawing, but about a second after, Cocoa set the cursor back to the arrow cursor.
I created a Symbolic break point on -[NSCursor set] to see where this is coming from and this is the call stack I get.
0 ??? 0x000000010cade785 0x0 + 4507690885,
1 Periscope HiDef4 0x00000001001d3f70 main + 0,
2 AppKit 0x00007fff4da7c55e __37+[NSDisplayCycle currentDisplayCycle]_block_invoke + 695,
3 QuartzCore 0x00007fff5b73b8c7 _ZN2CA11Transaction19run_commit_handlersE18CATransactionPhase + 49,
4 QuartzCore 0x00007fff5b73a389 _ZN2CA11Transaction6commitEv + 171,
5 AppKit 0x00007fff4e234a72 __65+[CATransaction(NSCATransaction) NS_setFlushesWithDisplayRefresh]_block_invoke + 283,
6 CoreFoundation 0x00007fff503ca737 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23,
7 CoreFoundation 0x00007fff503ca65f __CFRunLoopDoObservers + 511,
8 CoreFoundation 0x00007fff503ad128 __CFRunLoopRun + 1240,
9 CoreFoundation 0x00007fff503ac9b7 CFRunLoopRunSpecific + 487,
10 HIToolbox 0x00007fff4f68cd96 RunCurrentEventLoopInMode + 286,
11 HIToolbox 0x00007fff4f68cb06 ReceiveNextEventCommon + 613,
12 HIToolbox 0x00007fff4f68c884 _BlockUntilNextEventMatchingListInModeWithFilter + 64,
13 AppKit 0x00007fff4d93da73 _DPSNextEvent + 2085,
14 AppKit 0x00007fff4e0d3e34 -[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 3044,
15 AppKit 0x00007fff4d932885 -[NSApplication run] + 764,
16 AppKit 0x00007fff4d901a72 NSApplicationMain + 804,
17 Periscope HiDef4 0x00000001001d3f92 main + 34,
18 libdyld.dylib 0x00007fff7828a015 start + 1,
19 ??? 0x0000000000000003 0x0 + 3
I tried changing the implementation from using -[NSCursor set] and mouseEntered: events to -[NSView addCursorRect:cursor:] with a rect of the entire view bounds, but that wouldn't set the cursor at all, maybe because we are using an NSOpenGLView subclass?
The strange thing is the cursor is not always reset, if you click the button and pause and then move off the pallet we don't get the -[NSCursor set] with the above stack, its only if you move straight away, its possible its got something to do with the resize window frame cursor for the pallet changing, but I'm not sure.
I have come up with a hacky solution of using mouseMoved: to check the cursor is what its suppose to be, but it only works if the user moves the cursor and I would rather work out why I getting the unwanted -[NSCursor set] and fix that instead.

How to display callstack line numbers when my program is broken in Rust?

I use RUST_BACKTRACE=full ./my-program to run my compiled program.
However, I get a message like below which has only the function address without line numbers.
thread 'main' panicked at 'index out of bounds: the len is 6 but the index is 6', src/libcore/slice/mod.rs:734
stack backtrace:
0: 0x100a26463 - std::sys::imp::backtrace::tracing::imp::unwind_backtrace::hbdeac7eba2f064c6
1: 0x100a2786d - std::panicking::default_hook::{{closure}}::h9e0a6ca9bb64b479
2: 0x100a27434 - std::panicking::default_hook::h9043ae80af471c9f
3: 0x100a29f17 - std::panicking::rust_panic_with_hook::h05996066754c6be9
4: 0x100a29e04 - std::panicking::begin_panic::h9fecf34da42eb910
5: 0x100a29d22 - std::panicking::begin_panic_fmt::he5aad713258a67c3
6: 0x100a29c87 - rust_begin_unwind
7: 0x100a4a5f0 - core::panicking::panic_fmt::he26d734b771c5b2c
8: 0x100a4a568 - core::panicking::panic_bounds_check::h19dd3f615b4fea05
9: 0x100a1fc76 - <usize as core::slice::SliceIndex<[T]>>::index::h1f41340feec36937
10: 0x100a1f744 - core::slice::<impl core::ops::Index<I> for [T]>::index::h3246d2321fb7f789
11: 0x100a205b6 - sort::merge::h697218a53d5049aa
12: 0x100a20227 - sort::merge_sort::h10fe012581f48b43
13: 0x100a201e5 - sort::merge_sort::h10fe012581f48b43
14: 0x100a201e5 - sort::merge_sort::h10fe012581f48b43
15: 0x100a20159 - sort::merge_sort_pub::hb18b616b61510f3b
16: 0x100a20e24 - sort::main::hffac78b51f3ea2c3
17: 0x100a29c45 - std::panicking::try::do_call::h24a2756282b9a31c
18: 0x100a2ba2a - __rust_maybe_catch_panic
19: 0x100a2a1d0 - std::rt::lang_start::hd19f94db0c6a490e
20: 0x100a20fc9 - main
Is there any method to add the line numbers at the break spot?
This problem is a cross-platform issue and is tracked as Rust issue 24346. My workspace is macOS 10.12.4:
>rustc -vV
rustc 1.18.0-nightly (2564711e8 2017-04-04)
binary: rustc
commit-hash: 2564711e803f62e04bebf10408cc1c11297c0caf
commit-date: 2017-04-04
host: x86_64-apple-darwin
release: 1.18.0-nightly
LLVM version: 3.9
The workaround is to use a debugger to get the callstack information.
I have a hellobugs.rs file only present several lines of buggy code. At line 3, I cause a panic due to accessing the vector out of bounds:
fn main() { // 1
let v = vec![1, 2, 3]; // 2
println!("{}", v[4]); // 3
} // 4
Compile this with rustc hellobugs.rs -g -o hellobugs Don't forget the -g argument.
Running with RUST_BACKTRACE=full ./hellobugs will get backtraces but without line numbers on my macOS. As the issue says, we can use rust-lldb hellobugs to debug it and get detailed backtraces. Of course, using lldb is okay as well:
>rust-lldb hellobugs
...lots of rust-lldb message...
(lldb) breakpoint set -b rust_begin_unwind
Breakpoint 1: where = hellobugs`std::panicking::rust_begin_panic + 4 at panicking.rs:468, address = 0x000000010000a5b4
(lldb) r
Process 41626 launched: '/Users/xxx/bin/hellobugs' (x86_64)
hellobugs was compiled with optimization - stepping may behave oddly; variables may not be available.
Process 41626 stopped
* thread #1: tid = 0x6c3e39, 0x000000010000a5b4 hellobugs`std::panicking::rust_begin_panic + 4 at panicking.rs:468, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
frame #0: 0x000000010000a5b4 hellobugs`std::panicking::rust_begin_panic + 4 at panicking.rs:468 [opt]
(lldb) bt
* thread #1: tid = 0x6c3e39, 0x000000010000a5b4 hellobugs`std::panicking::rust_begin_panic + 4 at panicking.rs:468, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
* frame #0: 0x000000010000a5b4 hellobugs`std::panicking::rust_begin_panic + 4 at panicking.rs:468 [opt]
frame #1: 0x000000010002af51 hellobugs`core::panicking::panic_fmt + 129 at panicking.rs:69 [opt]
frame #2: 0x000000010002aec9 hellobugs`core::panicking::panic_bounds_check + 105 at panicking.rs:56 [opt]
frame #3: 0x0000000100001726 hellobugs`collections::vec::{{impl}}::index<i32>(self=0x00007fff5fbff720, index=4) + 118 at vec.rs:1426
frame #4: 0x0000000100001826 hellobugs`hellobugs::main + 182 at hellobugs.rs:3
frame #5: 0x000000010000a5a6 hellobugs`std::panicking::try::do_call<fn(),()> [inlined] core::ops::FnOnce::call_once<fn(),()> + 6 at ops.rs:2606 [opt]
frame #6: 0x000000010000a5a4 hellobugs`std::panicking::try::do_call<fn(),()> + 4 at panicking.rs:454 [opt]
frame #7: 0x000000010000c38b hellobugs`panic_unwind::__rust_maybe_catch_panic + 27 at lib.rs:98 [opt]
frame #8: 0x000000010000ab31 hellobugs`std::rt::lang_start [inlined] std::panicking::try<(),fn()> + 44 at panicking.rs:433 [opt]
frame #9: 0x000000010000ab05 hellobugs`std::rt::lang_start [inlined] std::panic::catch_unwind<fn(),()> at panic.rs:361 [opt]
frame #10: 0x000000010000ab05 hellobugs`std::rt::lang_start + 325 at rt.rs:57 [opt]
frame #11: 0x000000010000192a hellobugs`main + 42
frame #12: 0x00007fffdfc5f235 libdyld.dylib`start + 1
(lldb)
My results are as above. You can see at frame #4 there comes the buggy result of at hellobug.rs:3. This informs us the 3rd line has a bug. It is a little bother to use lldb and trace, but it's accurate!

How to tell if an application is in modal state

I want to be able to tell if my application is currently in a "modal" state.
I know that if it is in this state using Cocoa's functions, I could tell by checking where [[NSApplication sharedApplication] modalWindow] returns nil or not.
But it could also be in modal state using Carbon's functions (RunAppModalLoopForWindow etc), and then Cocoa's modalWindow does not tell us whether the application is modal.
Unfortunately, I don't have the choice to avoid Carbon as my app hosts old third party plugins which do use it.
Here's part of an example stack trace in a modal state due to carbon:
frame #12: 0x93ede739 CoreFoundation`__CFRunLoopRun + 1897
frame #13: 0x93eddd5a CoreFoundation`CFRunLoopRunSpecific + 394
frame #14: 0x93eddbbb CoreFoundation`CFRunLoopRunInMode + 123
frame #15: 0x930cee2d HIToolbox`RunCurrentEventLoopInMode + 259
frame #16: 0x930cebb2 HIToolbox`ReceiveNextEventCommon + 526
frame #17: 0x93119c4a HIToolbox`AcquireNextEventInMode + 75
frame #18: 0x93269aea HIToolbox`_AcquireNextEvent + 58
frame #19: 0x932585dc HIToolbox`_RunAppModalLoop + 168
frame #20: 0x932584ee HIToolbox`RunAppModalLoopForWindow + 130
I could trace the stack and see that _RunAppModalLoop is there, but I don't like this solution.
You can try checking the output from GetWindowModality([[NSApp keyWindow] windowRef], ...) and/or the same applied to the -mainWindow.
You can see if -[NSRunLoop currentMode] is NSDefaultRunLoopMode.
However, you might get a different answer with a question more specific to the problem you're trying to solve.
This can be done by enumerating all the app's windows and checking if they are modal by using GetWindowModality.
bool isAnyCarbonWindowModal()
{
for (
WindowRef win = GetFrontWindowOfClass(kAllWindowClasses, true);
win != nullptr;
win = GetNextWindowOfClass(win, kAllWindowClasses, true))
{
WindowModality modalKind;
WindowRef unavailableWindow;
GetWindowModality(win, &modalKind, &unavailableWindow);
if (kWindowModalityAppModal == modalKind)
return true;
}
return false;
}

MKMapView setRegion: animated: crashes the app (edited)

I have a MKMapView that expands (vertically) on tap (using UITapGestureRecognizer) and fires off an api call on pan (using UIPanGestureRecoginizer).
Everything was working fine, until some time back, where on Panning, the app would crash, with hardly any useful info (or info that I could comprehend)
Exception breakpoints are on, and zombie objects have been enabled. On crashing, it never hits the exception breakpoint!
Here's the log:
(Panning began, panning, panning ended are printed out based on the Pan gestureRecognizer states).
Right after panning ends, the app crashes.
(The map is yet to load all its tiles, and regionDidChangeAnimated is not called yet):
2013-01-17 14:46:04.396 MyApp[13126:c07] Panning Began
2013-01-17 14:46:04.412 MyApp[13126:c07] Panning
2013-01-17 14:46:04.412 MyApp[13126:c07] Panning
2013-01-17 14:46:04.557 MyApp[13126:c07] Panning
2013-01-17 14:46:04.606 MyApp[13126:c07] Panning
2013-01-17 14:46:04.691 MyApp[13126:c07] Panning Ended
2013-01-17 14:46:04.692 MyApp[13126:c07] *** -[MKMapViewPositioningChange hasChanges]: message sent to deallocated instance 0x139f7520
Here's the backtrace i see after the crash:
(lldb) bt
* thread #1: tid = 0x1c03, 0x02a4fa97 CoreFoundation`___forwarding___ + 295, stop reason = EXC_BREAKPOINT (code=EXC_I386_BPT, subcode=0x0)
frame #0: 0x02a4fa97 CoreFoundation`___forwarding___ + 295
frame #1: 0x02a4f94e CoreFoundation`_CF_forwarding_prep_0 + 14
frame #2: 0x01244d27 MapKit`-[MKMapView(UserPositioningInternal) _runPositioningChange] + 2037
frame #3: 0x01242dd7 MapKit`-[MKMapView(UserPositioningInternal) _runPositioningChangeIfNeeded:] + 86
frame #4: 0x01240220 MapKit`-[MKMapViewInternal runPositioningChangeIfNeeded] + 50
frame #5: 0x01e2eb90 Foundation`__NSFireTimer + 97
frame #6: 0x02a1f376 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 22
frame #7: 0x02a1ee06 CoreFoundation`__CFRunLoopDoTimer + 534
frame #8: 0x02a06a82 CoreFoundation`__CFRunLoopRun + 1810
frame #9: 0x02a05f44 CoreFoundation`CFRunLoopRunSpecific + 276
frame #10: 0x02a05e1b CoreFoundation`CFRunLoopRunInMode + 123
frame #11: 0x03c897e3 GraphicsServices`GSEventRunModal + 88
frame #12: 0x03c89668 GraphicsServices`GSEventRun + 104
frame #13: 0x0132d65c UIKit`UIApplicationMain + 1211
frame #14: 0x0001223d MyApp`main + 141 at main.m:16
frame #15: 0x00002fc5 MyApp`start + 53
The crashes go away the moment i take the connection for the PanGestureRecognizer action method.
Is there a way to get rid of this crash while using the gesture recognizers? or is there a way to know that the map was tapped and panned, without using GestureRecognizers?
Any help/questions/answers/comments appreciated!
Update (Jan 19): This doesn't seem to be an issue with the pan gesture recognizer at all. Now I am getting it to crash on after i try to add new annotations to the mapview, call [MapView setRegion: animated:], and crashes just before regionDidChangeAnimated is hit, with the same [MKMapViewPositioningChange hasChanges] log at the point where it crashes.
Update (Jan 23): I think I am quite sure whats happening. there is one chunk of code thats trying to set the region to include all the annotations in the visible rect of the MKMapView, and a few other locations, where I am calling [myMapView removeAnnotations:[myMapView annotations]]. And, my guess is that these two actions end up in a nasty mid-air collision, leaving no trail as to what lead to a crash. Will update the question with an answer if my hunch-fix passes QA
As I had guessed earlier (second update to the question), this was an issue with trying the add set the map region to show all annotations, and removing all annotations simultaneously. if you are calling setRegion: animated: , make sure to check if the mapView has at least one annotation.
Also, it'll be helpful to use the following piece of code judiciously, especially if you are doing any type of animations on the map based on the annotations.
[MKMapView removeAnnotations:[MKMapView annotations]];

How to track down the line that's causing a runtime error?

My app is crashing with this error message:
'NSInvalidArgumentException', reason: '-[__NSCFDictionary setObject:forKey:]: attempt to insert nil value (key: 0)'
and I am trying to find where this is occuring in my code. I have set NSZombiesEnabled in the environment variables, however it's pretty hard to figure out the location. Any idea on how to debug?
I typed in bt and here's what I see:
frame #0: 0x30d1832c libsystem_kernel.dylib`__pthread_kill + 8
frame #1: 0x3597d20e libsystem_c.dylib`pthread_kill + 54
frame #2: 0x3597629e libsystem_c.dylib`abort + 94
frame #3: 0x35055f6a libc++abi.dylib`abort_message + 46
frame #4: 0x3505334c libc++abi.dylib`_ZL17default_terminatev + 24
frame #5: 0x36c38356 libobjc.A.dylib`_objc_terminate + 146
frame #6: 0x350533c4 libc++abi.dylib`_ZL19safe_handler_callerPFvvE + 76
frame #7: 0x35053450 libc++abi.dylib`std::terminate() + 20
frame #8: 0x35054824 libc++abi.dylib`__cxa_rethrow + 88
frame #9: 0x36c382a8 libobjc.A.dylib`objc_exception_rethrow + 12
frame #10: 0x3428d50c CoreFoundation`CFRunLoopRunSpecific + 404
frame #11: 0x3428d36c CoreFoundation`CFRunLoopRunInMode + 104
frame #12: 0x3826f438 GraphicsServices`GSEventRunModal + 136
frame #13: 0x36d27cd4 UIKit`UIApplicationMain + 1080
frame #14: 0x00051cdc AppName`main + 80 at main.m:16
Add exceptions as a breakpoint. Assuming Xcode 4+...
At the top of the navigator frame (where you view files and such), you will see a little icon that looks like a sideways arrow.
That will show the breakpoint navigator. At the bottom of that view, click the + to add a breakpoint.
Click on "Add exception breakpoint..."
The default option is probably fine... you want to break on throw of all exceptions.
Now, when you run, you will get a breakpoint anywhere your app throws an exception.
Is the error happening in your testing? Are you seeing it from crash logs from iTunes Connect?
If you are able to reproduce it locally, run the scenario to duplicate the error and when the debugger becomes active, type "bt" at the (gdb) prompt in the Console for a stacktrace with a line number.
Try to add this part of code in your AppDelegate :
void uncaughtExceptionHandler(NSException *exception);
void uncaughtExceptionHandler(NSException *exception) {
NSLog(#"CRASH: %#", exception);
NSLog(#"Stack Trace: %#", [exception callStackSymbols]);
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);
// your previous code here
return YES;
}
Next time your error occurs, you should have some additional infos on the crash.

Resources