0

I'm building a simple Cocoa app from scratch, and right now I have a working app with one window.

The problem is it crashes on every ~10th run in [NSApp nextEventMatchingMask]. Here's the code:

#include <Cocoa/Cocoa.h>

void wait_for_events() {
  NSEvent *event = [NSApp nextEventMatchingMask:NSEventMaskAny
                                      untilDate:[NSDate distantFuture]
                                         inMode:NSDefaultRunLoopMode
                                        dequeue:YES]; 
  [NSApp sendEvent:event];
}

int main() {
  NSApplication sharedApplication];
  [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
  [NSApp finishLaunching];
  NSUInteger windowStyle =
  NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask;                                    
  NSWindow *window =
      [[NSWindow alloc] initWithContentRect:NSMakeRect(0,0,300,300)
                                  styleMask:windowStyle
                                    backing:NSBackingStoreBuffered
                                      defer:NO];
                                      [window center];
  [window retain];
  [window orderFrontRegardless];                               

  //[NSApp run];
  while (1) {
    wait_for_events();
  }
}

I need access directly to the event loop, so I can't call [NSApp run]. I copied wait_for_events code from glfw.

I tried adding autorelease pool and disabling ARC via -fno-objc-arc

I tried this on 2 different machines with Sierra and High Sierra and still getting random EXC_BAD_ACCESS crashes:

Process 4925 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
    frame #0: 0x00007fff50049290 libobjc.A.dylib`objc_destructInstance + 32
libobjc.A.dylib`objc_destructInstance:
->  0x7fff50049290 <+32>: andq   0x20(%rax), %rcx
    0x7fff50049294 <+36>: movb   0x2(%rcx), %cl
    0x7fff50049297 <+39>: andb   $0x2, %cl
    0x7fff5004929a <+42>: shrb   %cl
Target 0: (a.out) stopped.
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
  * frame #0: 0x00007fff50049290 libobjc.A.dylib`objc_destructInstance + 32
    frame #1: 0x00007fff2973a201 CoreFoundation`_CFRelease + 1025
    frame #2: 0x00007fff29600cf4 CoreFoundation`__CFBasicHashDrain + 388
    frame #3: 0x00007fff29739f1c CoreFoundation`_CFRelease + 284
    frame #4: 0x00007fff2967f68c CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 12
    frame #5: 0x00007fff296620a3 CoreFoundation`__CFRunLoopDoBlocks + 275
    frame #6: 0x00007fff2966172e CoreFoundation`__CFRunLoopRun + 1278
    frame #7: 0x00007fff29660fa3 CoreFoundation`CFRunLoopRunSpecific + 483
    frame #8: 0x00007fff28980866 HIToolbox`RunCurrentEventLoopInMode + 286
    frame #9: 0x00007fff289804df HIToolbox`ReceiveNextEventCommon + 366
    frame #10: 0x00007fff28980354 HIToolbox`_BlockUntilNextEventMatchingListInModeWithFilter + 64
    frame #11: 0x00007fff26c7da23 AppKit`_DPSNextEvent + 2085
    frame #12: 0x00007fff27412e6c AppKit`-[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 3044
    frame #14: 0x0000000100011ef9 a.out`wait_for_events + 9
    frame #15: 0x0000000100016030 a.out`main + 7
    frame #16: 0x00000001000013f4 a.out`start + 52
Alex
  • 34,581
  • 26
  • 91
  • 135
  • 1
    I can't reproduce this crash; is this the actual code? How is this working without sending `sendEvent:`? I would expect the main window not to work at all. (See https://stackoverflow.com/questions/48020222/how-to-make-nsapp-run-not-block for any example of how GLFW actually does this.) Why are you turning off ARC (and also over-retaining `window`)? – Rob Napier Apr 12 '18 at 00:05
  • My suspicion is that you're mismanaging memory somewhere; probably over-releasing something. Turn on ARC. There hasn't been a good reason to turn it off in years. – Rob Napier Apr 12 '18 at 00:07
  • Right, I forgot to include sendEvent. – Alex Apr 12 '18 at 00:29
  • This is pretty much the entire code. There's also an OpenGL context creation and a glClear call. I went through the code with clang analyzer, still nothing. But yeah it's definitely a memory problem, no idea how to debug this... – Alex Apr 12 '18 at 00:54
  • 1
    Enable `NSZombies`. https://stackoverflow.com/questions/5386160/how-to-enable-nszombie-in-xcode (But I don't see any crash with the above code here.) BTW, `orderFrontRegardless` is a very unusual method to call (and is rarely the right one). The normal method is `makeKeyAndOrderFront:`. (I can't imagine that being related.) – Rob Napier Apr 12 '18 at 11:53
  • Ok thanks, will do. I was hoping to resolve this without installing 10 GB of xcode. Looks like there's no command line utility for Zombies. – Alex Apr 13 '18 at 00:21
  • Just set the environment variable: `NSZombieEnabled=YES`. https://developer.apple.com/library/content/technotes/tn2124/_index.html#//apple_ref/doc/uid/DTS10003391-CH1-SECZOMBIES – Rob Napier Apr 13 '18 at 00:33
  • I installed xcode and I'm no longer getting the EXC_BAD_ACCESS when using the Zombie GUI instrument. I couldn't make it work via the command line. The link you referenced uses gdb, and I use lldb, I assume it should work too. `NSZombieEnabled=YES lldb a.out` gives me the same backtrace. – Alex Apr 13 '18 at 04:45
  • This objective-c code was being called from another C code base, and I had to manually remove lots of function calls to track down a function with an uninitialized pointer. Really surprised lldb didn't help me here at all. Thanks for you help and sorry for wasting your time @RobNapier. – Alex Apr 13 '18 at 06:33

1 Answers1

0

I figured it out. There was another function with an uninitialized pointer.

I didn't even realize it was being called.

Somehow lldb didn't help me track it down.

Alex
  • 34,581
  • 26
  • 91
  • 135