NSRunningApplication crashes

Lately, we are experiencing intermittent segfault crashes related to NSRunningApplication: they happen mostly when _fetchDynamicProperties is about to send the _applyPropertyChanges:fromDictionary:. occasionally elsewhere. The problem seems to be related to a concurrent XPC communication (unproven, but probable — so far, it never crashed unless the application was at the same moment communicating through XPC).


It happens pretty randomly, alas. Only once I've been able to catch the problem in Xcode; looked like this (inside of _fetchDynamicProperties):


    0x7fff2e655188 <+522>: callq  0x7fff2f1b5078            ; symbol stub for: CFRelease
    0x7fff2e65518d <+527>: testq  %r15, %r15
    0x7fff2e655190 <+530>: je     0x7fff2e655206            ; <+648>
    0x7fff2e655192 <+532>: xorl   %eax, %eax
    0x7fff2e655194 <+534>: cmpb   $0x0, -0x93(%rbp)
    0x7fff2e65519b <+541>: sete   %al
    0x7fff2e65519e <+544>: leaq   0x2(,%rax,4), %rcx
    0x7fff2e6551a6 <+552>: shlq   $0x2, %rax
    0x7fff2e6551aa <+556>: cmpb   $0x0, -0x98(%rbp)
    0x7fff2e6551b1 <+563>: cmovneq %rcx, %rax
    0x7fff2e6551b5 <+567>: leaq   0x40(%rax), %rcx
    0x7fff2e6551b9 <+571>: cmpb   $0x0, -0x92(%rbp)
    0x7fff2e6551c0 <+578>: cmovneq %rax, %rcx
    0x7fff2e6551c4 <+582>: movq   %rcx, %rax
    0x7fff2e6551c7 <+585>: orq    $0x20, %rax
    0x7fff2e6551cb <+589>: testb  %bl, %bl
    0x7fff2e6551cd <+591>: cmovneq %rcx, %rax
    0x7fff2e6551d1 <+595>: movq   %rax, %rdx
    0x7fff2e6551d4 <+598>: orq    $0x80, %rdx
    0x7fff2e6551db <+605>: testb  %r14b, %r14b
    0x7fff2e6551de <+608>: cmovneq %rax, %rdx
    0x7fff2e6551e2 <+612>: movq   0x5d60ab2f(%rip), %rsi    ; "_applyPropertyChanges:fromDictionary:"
    0x7fff2e6551e9 <+619>: movq   %r13, %rdi
    0x7fff2e6551ec <+622>: movq   %r15, %rcx
    0x7fff2e6551ef <+625>: callq  *0x5d2f5eb3(%rip)         ; (void *)0x00007fff5b7dd680: objc_msgSend
->  0x7fff2e6551f5 <+631>: movq   %r15, %rdi                           Thread 1: EXC_BAD_ACCESS (code=1, address=0x3eadddadca38)
    0x7fff2e6551f8 <+634>: callq  0x7fff2f1b5078            ; symbol stub for: CFRelease


Some crashlogs (and longer copy of the above, which includes also a bt) at http://ocs.cz/CD/NSRunningApp_crash.zip


Is it possible that this is caused anyhow by our code? Based on the docst I believe NSRunningApplication should be thread-safe. Can you recommend a work-around? The problem is rather at the inconvenient side.


Thanks a lot,

OC

Replies

The documentation has a really big caveat to that thread safety issue. It seems like most of those two paragraphs could be re-written to state: "NSRunningApplication is thread safe. LOL! Yeah, don't use this anythwere but the main thread."

First and important thing — as can be seen in the crashlogs (and as I did not stress out here, sorry for that), it does happen to crash in the main thread 😟


Aside of that (and unimportant) — myself, I read in there something quite different, namely, something like “use anywhere safely, just don't be surprised if the values change somewhat wildly” (which won't affect our usage). Especially I can't read in there anything about a danger of a crash. Might you have a different documentation? What I see in there is


>

NSRunningApplication
is thread safe, in that its properties are returned atomically. However, it is still subject to the main run loop policy described above. If you access an instance of
NSRunningApplication
from a background thread, be aware that its time-varying properties may change from under you as the main run loop runs (or not).

Anyway... that said, do you think it might help to write (and use) our own NSRunningApplication wrapper, which would simply super (or perhaps rather forward using embedding instead of subclassing) all the messages inside of a @synchronized(self) harness? I have considered trying that myself originally, but having read that NSRunningApplication is thread safe in the docs, I have decided it would be a waste of time. Was I wrong and should I try that anyway?

There is always an inherent risk of a crash in any API. The docs don't need to specify that.


You are the one to bring up threading, so that's why I mentioned it.


You are looking in the wrong place for the crash. Something may crash deep within Apple's code because you didn't do something properly in your code 9 function calls higher in the stack. Are you using blocks? Are you copying them correctly? Some blocks live on the stack and have to be copied into the heap before you can treat them like an Objective-C object.

It's possible there's a bug in NSRunningApplication, but I'd look elsewhere first. In particular, you may have a memory smashing bug elsewhere in code unrelated to NSRunningApplication.


Try the usual "code hygiene" steps. Enable applicable warnings and fix them. Perform static analysis on your code and fix the issues it finds. Run your code with the various sanitizers, especially the thread sanitizer. Run your code under the Zombies template of Instruments.