EXC_BAD_INSTRUCTION SIGILL

I have an interesting crash case that basically just points the finger into one method. NodeFactory.appendChildren()

This method is parsing results from getattrlistbulk() and uses some code excerpts from the following developer discussion Getting inode number from URL

The entire app has been using swift for the least couple of years and slowly evolving to use less and less C/Objective-C

Exception Type:        EXC_BAD_INSTRUCTION (SIGILL)
Exception Codes:       0x0000000000000001, 0x0000000000000000
Exception Note:        EXC_CORPSE_NOTIFY

Termination Signal:    Illegal instruction: 4
Termination Reason:    Namespace SIGNAL, Code 0x4
Terminating Process:   exc handler [3386]

...
Thread 8 Crashed:: Dispatch queue: NSOperationQueue 0x7f83aa104920 (QOS: USER_INTERACTIVE)
0   com.bla.myapp	0x000000010f5bd8f0 NodeFactory.appendChildren(_:_:_:_:_:) + 4544
1   com.bla.myapp	0x000000010f5bf15b NodeFactory.fetchChildren(_:) + 1163
2   com.bla.myapp	0x000000010f5bf9ca NodeFactory.fetch(nodeEntry:) + 90
3   com.bla.myapp	0x000000010f5c041f partial apply for closure #3 in NodeFactory.fetch(nodeEntry:) + 127
4   com.bla.myapp	0x000000010f5505fe thunk for @escaping @callee_guaranteed () -> () + 14
5   com.apple.Foundation          	0x00007fff33b72ac5 __NSBLOCKOPERATION_IS_CALLING_OUT_TO_A_BLOCK__ + 7
6   com.apple.Foundation          	0x00007fff33b729e6 -[NSBlockOperation main] + 80
7   com.apple.Foundation          	0x00007fff33b72981 __NSOPERATION_IS_INVOKING_MAIN__ + 17
8   com.apple.Foundation          	0x00007fff33b71bb3 -[NSOperation start] + 722


A more seasoned programmer might see a bug in the body of the appendChildren(). However I'm interested in tips/flags to Xcode Settings so that apple's crash reporter is able to collect and provide more clues in the crash report.

The current Xcode has:

Debug Information Format = DWARF
Strip Debug Symbols = NO
Optimization Level = Fastest

Thank you.

Consider this:

Exception Type:        EXC_BAD_INSTRUCTION (SIGILL)

On 64-bit Intel this usually means that you’ve hit a Swift trap (which, on that platform, is implemented by the ud2 instruction).

Now this:

0   com.bla.myapp … NodeFactory.appendChildren(_:_:_:_:_:) + 4544

That offset, 4544, is pretty large. Is NodeFactory.appendChildren(…) a big function? If not, it’s possible that you’re suffering from incomplete symbolication.

Regardless, you need to further symbolicate this log to get source file names and line numbers for frames 4 through 0. See Adding Identifiable Symbol Names to a Crash Report.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Went through the entire process of fully symbolicating a crash. And I was rewarded with some more gold nuggets.

NodeFactory.appendChildren(_:_:_:_:_:_:) (in com.id-design.v7.whatsizehelper) (NodeFactory.swift:256)

let modTimeInSeconds: Int32 = {}() is obviously crashing.

Also another clue, it crashes always on the same folder. So the meta data for this folder is 'wrong' ?

            let modTimeInSeconds: Int32 = {
                if (returned.commonattr & attrgroup_t(bitPattern: ATTR_CMN_MODTIME)) != 0 {
                    aligningBuffer.copyMemory(from: UnsafeRawBufferPointer(start: field, count: MemoryLayout<timespec>.size))
                    let time = aligningBuffer.baseAddress!.load(as: timespec.self)
                    // the following will fails cause of memory misalignment
                    // let time = field.load(as: timespec.self)
                    field += MemoryLayout<timespec>.size
                    return Int32(time.tv_sec)
                }
                return 0
            }()

So the meta data for this folder is 'wrong' ?

It’s hard to offer any insight here without more info. However, my guess is that you’re just ‘holding this wrong’? getattrlistbulk is a notoriously tricky API to call correctly but it also central to high-performance file system access on the Mac, so if it were misbehaving then I’d expect to see other stuff fail.

Can you boil this down to a more focused example? Try this:

  1. Move the problematic directory into a directory with much less content.

  2. If the problem reproduces, run your code and set a breakpoint on the line where you call getattrlistbulk. Print the inputs you give it.

  3. Step over that. Hex dump the output.

  4. Post those details here.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

I could share some more code on a direct message basis, it you are up for a challenge. My pain is that I can't reproduce it. It just happens on a few 'lucky' customer machines. And these machines are recent. No old software or old file systems.

I will add the 'ATTR_CMN_ERROR' and see if that will prevent me from digging deeper into trouble. It is possible these troubled folders are returning some error and instead of bailing out early I'm continuing to read the rest of the pointer.

This class, the one that uses the getattrlistbulk was my last one to move to swift. The previous version using Objective-C was working. Mixing both obj-c and swift requires much more mental effort. Imagine speaking English and French in the same conversation randomly.

Maybe I should eat it and revert this back the C base implementation.

Again thank you very much for the tips.


Klajd Deda let myEmail = "kdeda" + "@" + "mac.com"

The ATTR_CMN_ERROR is not triggered.

As as soon as we hit this particular folder boom, we manage to collect ATTR_CMN_NAME, ATTR_CMN_FSID and ATTR_CMN_OBJTYPE and than as soon as we attempt to fetch the ATTR_CMN_MODTIME, boom.

So we are crashing on the same darn portion. Maybe I should revert this module back to the c version.

            let modTimeInSeconds: Int32 = {
                if (returned.commonattr & attrgroup_t(bitPattern: ATTR_CMN_MODTIME)) != 0 {
                    aligningBuffer.copyMemory(from: UnsafeRawBufferPointer(start: field, count: MemoryLayout<timespec>.size))
                    let time = aligningBuffer.baseAddress!.load(as: timespec.self)
                    // the following will fails cause of memory misalignment
                    // let time = field.load(as: timespec.self)
                    field += MemoryLayout<timespec>.size
                    return Int32(time.tv_sec)
                }
                return 0
            }()

I could share some more code on a direct message basis, it you are up for a challenge.

I’m happy to do that in the context of a DTS tech support incident.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

@eskimo, I did open ticket #787511160 and can provide the main class that calls the getattrlistbulk

Thanks.

EXC_BAD_INSTRUCTION SIGILL
 
 
Q