Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Crash in [NSWindow orderFrontRegardless] after updating to macOS Mojave

Getting this weird crash after updating to Mojave.

Not doing anything special, just creating an NSWindow and calling orderFrontRegardless

Always worked fine before.

1   libsystem_platform.dylib            0x00007fff6610ab5d _sigtramp + 29
2   ???                                 0x0000000000000000 0x0 + 0
3   CoreFoundation                      0x00007fff39b00bb6 __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 12
4   CoreFoundation                      0x00007fff39b00b30 ___CFXRegistrationPost_block_invoke + 63
5   CoreFoundation                      0x00007fff39b00a9a _CFXRegistrationPost + 404
6   CoreFoundation                      0x00007fff39b08f48 ___CFXNotificationPost_block_invoke + 87
7   CoreFoundation                      0x00007fff39a71994 -[_CFXNotificationRegistrar find:object:observer:enumerator:] + 1642
8   CoreFoundation                      0x00007fff39a70d47 _CFXNotificationPost + 732
9   Foundation                          0x00007fff3bdab217 -[NSNotificationCenter postNotificationName:object:userInfo:] + 66
10  AppKit                              0x00007fff3720538b -[NSWindow _setFrameCommon:display:stashSize:] + 3090
11  AppKit                              0x00007fff37204766 -[NSWindow _setFrame:display:allowImplicitAnimation:stashSize:] + 192
12  AppKit                              0x00007fff3720469f -[NSWindow setFrame:display:] + 51
13  AppKit                              0x00007fff3727aca9 -[NSWindow _reallyDoOrderWindowAboveOrBelow:relativeTo:findKey:forCounter:force:isModal:] + 1336
14  AppKit                              0x00007fff372792a0 -[NSWindow _doOrderWindow:relativeTo:findKey:forCounter:force:isModal:] + 283
15  AppKit                              0x00007fff37a0dce9 -[NSWindow orderFrontRegardless] + 40

Code (it's a console app):

NSWindow *window =    [[NSWindow alloc] initWithContentRect:windowRect
styleMask:windowStyle
backing:NSBackingStoreBuffered
defer:NO];

// Since Snow Leopard, programs without application bundles and Info.plist
// files don't get a menubar and can't be brought to the front unless the
// presentation option is changed
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];

 [NSApp activateIgnoringOtherApps:YES];
 [window makeKeyAndOrderFront:nil];
like image 763
Alex Avatar asked Feb 18 '19 20:02

Alex


2 Answers

How do you initialize the app? Do you have NSApplication initialized before using AppKit?

Something like these steps should be necessary in main.m:

@autoreleasepool {
    NSApplication* application = NSApplication.sharedApplication;

    AppDelegate* delegate = [[AppDelegate alloc] init];
    application.delegate = delegate;

    [application run];
}

Also your delegate might be getting deallocated, since NSApp holds a weak reference to it.

like image 63
pointum Avatar answered Oct 30 '22 02:10

pointum


You indicated that you were dereferencing an uninitialized pointer. But, I don't have enough information from the report you posted to know if this was (perhaps by luck) null, or just garbage memory. I'll assume that at some point you crashed with an EXC_BAD_ACCESS (signal equivalent is SIGBUS or SIGSEGV, depending).

The critical bit of information here was that you had a signal handler installed.

Signal handlers generally (but not always) run on the crashing thread using the same stack. The kernel injects the handler using that _sigtramp function. Upon signal delivery, current stack state contained the information you needed to track down the bad memory access. But, your signal handler was invoked instead. So it ran, mutating the stack as it did.

Then, your signal handler completed somehow. It is possible to configure a signal handler using sigaction such that the process state is restored to the moment just before the crashing event. I'm not sure how your signal handler was configured. But, ultimately, I'm going to assume that the process was allowed to exit.

At this point, Apple's ReportCrash would have been triggered, and would capture backtraces for all threads in whatever state your signal handler left them. This is critical, because that's not necessarily the crashing state.

Adding complexity, backtrace_symbols_fd is not at all safe to use from a signal handler. Async safety is challenging, and running code from a signal handler is highly difficult to get right. There are very few things you can do safely. I'm pretty sure, additionally, that backtrace_symbols_fd allocates memory. So, if your crash was in the memory allocator somewhere, and it sounds like it was, you were definitely at risk for a deadlock. Judging by the backtrace, it seems like that's exactly what might have happened. Check out man sigaction for some details.

Worse, unwinding the stack over a signal handler frame is particularly challenging because of the magic the kernel does to run your handler. That's why that ??? frame is in there.

A summary:

Without a signal handler installed, Apple's ReportCrash would have produced a correct (and likely helpful) backtrace for the crashing thread.

The stack trace you've included isn't great, but it's hard to know exactly why. It appears that backtrace_symbols_fd didn't do a good job of unwinding, possibly due to it being inappropriate to use from a signal handler, possibly because it isn't backed by a good-enough stack unwinding mechanism for this situation. But, without more information, it's difficult for me to know. I am surprised the the top frame was _sigtramp, though. That doesn't make a lot of sense. It makes me think something might have been going wrong in the signal handler itself. It is possible to crash a second time in your handler.

Apple's backtraces (generated by ReportCrash, backtrace_symbols_fd, or NSThread's callStackReturnAddresses, for example) can definitely be trusted, provided you're careful to use them in safe contexts.

like image 1
Mattie Avatar answered Oct 30 '22 01:10

Mattie