Swift run time exception like NSSetUncaughtExceptionHandler

Hi Team,

Would like to handle swift run time errors like EXC_BAD_INSTRUCTION with common exception handler like NSSetUncaughtExceptionHandler.

Could not find any such interface to register for generic exceptions.


Also tried below for registering for objective c exceptions:


NSSetUncaughtExceptionHandler { exception in

print(exception.callStackSymbols)

}

and this is not being invoked for Swift exception like

let test:String? = nil

let throwsException = test!


Is there a generic exception handler that we could extend or register our own exception handler in Swift?

Thanks in Advance!

Accepted Reply

I want to expand on jonprescott’s answer a little (well, more than a little :-)…

There are three things that folks commonly call exceptions:

  • Language exceptions, for example, an

    NSException
    that you throw in Objective-C via
    @throw
  • Swift errors, which use a syntax that looks a lot like the syntax used for language exceptions in other languages

  • Machine exceptions, for example, if you access an address that’s not mapped into your address space

In addition, there are Swift traps, which are machine exceptions raised by the Swift runtime when it detects a problem, for example, unwrapping an optional that’s

nil
[1].

When discussing exceptions you have to clearly distinguish between these types, lest you get very confused. For example, in your specific question you’re asking whether it’s possible to use a language exception facility (

NSSetUncaughtExceptionHandler
) to catch a machine exception (
EXC_BAD_INSTRUCTION
), which is obviously nonsense [2].

There are two mechanisms to handle machine exceptions:

  • Mach exception handlers

  • UNIX signals

You can see this dichotomy reflected in your average crash report, which includes both a Mach exception code (for example,

EXC_BAD_INSTRUCTION
) and a UNIX signal (continuing that example,
SIGILL
).

The relationship between these is complex, but the gist is that Mach exceptions are the underlying system used by the kernel which, under specific circumstances, will route the Mach exception through the UNIX signal handling infrastructure to allow for POSIX API compatibility.

Both of these mechanisms are extremely hard to use correctly. For an insight into those difficulties, check out my Implementing Your Own Crash Reporter post.

And that brings us to the inevitable follow-up question: What are you really trying to do? Can you give us some background on your overall goal here?

By way of context, most folks who ask questions like this are trying to achieve some goal that seems simple but is, in reality, stunningly difficult, for example, implementing their own crash reporter.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

[1] I just posted a short list of common causes on this thread.

[2] Although not everyone agrees with me on that point, at least historically. macOS has the ExceptionHandling framework which can catch machine exceptions and convert them to language exceptions. IMO this is utter madness, and I’m very glad it didn’t make the leap to iOS.

Replies

EXC_BAD_INSTRUCTION is also known as SIGILL (illegal instruction signal), and is actually a signal, something like a hardware interrupt, not an exception. If you want to handle these signals, you need to go into C-land and set up a signal handler, and using something like sigaction(2) set up the handler to handle the signal. If you look through the man pages on signaction (2), kill (2), etc., you'll get a feel for signals and signal handling. The default handler prints the signal name, other diagnostic info, then terminates the process, as you have observed.

I want to expand on jonprescott’s answer a little (well, more than a little :-)…

There are three things that folks commonly call exceptions:

  • Language exceptions, for example, an

    NSException
    that you throw in Objective-C via
    @throw
  • Swift errors, which use a syntax that looks a lot like the syntax used for language exceptions in other languages

  • Machine exceptions, for example, if you access an address that’s not mapped into your address space

In addition, there are Swift traps, which are machine exceptions raised by the Swift runtime when it detects a problem, for example, unwrapping an optional that’s

nil
[1].

When discussing exceptions you have to clearly distinguish between these types, lest you get very confused. For example, in your specific question you’re asking whether it’s possible to use a language exception facility (

NSSetUncaughtExceptionHandler
) to catch a machine exception (
EXC_BAD_INSTRUCTION
), which is obviously nonsense [2].

There are two mechanisms to handle machine exceptions:

  • Mach exception handlers

  • UNIX signals

You can see this dichotomy reflected in your average crash report, which includes both a Mach exception code (for example,

EXC_BAD_INSTRUCTION
) and a UNIX signal (continuing that example,
SIGILL
).

The relationship between these is complex, but the gist is that Mach exceptions are the underlying system used by the kernel which, under specific circumstances, will route the Mach exception through the UNIX signal handling infrastructure to allow for POSIX API compatibility.

Both of these mechanisms are extremely hard to use correctly. For an insight into those difficulties, check out my Implementing Your Own Crash Reporter post.

And that brings us to the inevitable follow-up question: What are you really trying to do? Can you give us some background on your overall goal here?

By way of context, most folks who ask questions like this are trying to achieve some goal that seems simple but is, in reality, stunningly difficult, for example, implementing their own crash reporter.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

[1] I just posted a short list of common causes on this thread.

[2] Although not everyone agrees with me on that point, at least historically. macOS has the ExceptionHandling framework which can catch machine exceptions and convert them to language exceptions. IMO this is utter madness, and I’m very glad it didn’t make the leap to iOS.