More than two years ago, I posed a very similar question: "could someone PLEASE let me have the contents of just the fatal error string or similar", and it's hard to believe that after nearly 4 years of Swift, we still have no way of getting this vital info out of a crashing program:
The Swift compiler in development now emits fatal error traps with an artificial inline frame, which will allow crash reporters than understand debug info to show the error directly as part of the backtrace. Future toolchains that include this change should be able to do better.
Iâd like to necro this thread. More information in crash logs is good, but a crash log canât always be correlated with, say, an external logging system that gets submitted to support by the user. Having the ability to write the fatal error and maybe the backtrack to the external log, and at least try to flush it, would be invaluable.
Can this functionality be abused? (say, by restarting the run loop) Yes, it can. Can it result in even worse behavior? Yes it can, but not worse than anything you can do with threads (your thread can always be suspended between the cmp and the jmp swift_reportFatalError). Is it still useful? Yes, absolutely.
Is there a useful feature handling actor-isolated recovery that does not have to result in process termination? Perhaps. Will the currently-proposed feature handle all kinds of exits? Definitely not. Would this preclude any such expansion in the future? Nope!
Is it hard to implement? Nope, the code is already well-factored for it! Will it cost anything at the fatal error site? Nope, thereâs already a call there! Can it be backwards-deployed? Not easily (none of these symbols were planned as interposable), but maybe someone clever can figure something out. If not itâs still worth it, though.
(Personally I think supporting multiple handlers is a good idea, but chainable handlers is technically sufficient: fetch the old handler, capture it into your new handler, call it when youâre done with your own work.)
There are still a lot of bare traps that are directly generated by the compiler, integer overflow checks being the typical example, and I think we'd want to reserve the right to reduce fatal errors with static strings into traps with inline frames in the future too. I think a crash interceptor is something we could reasonably provide, but I also think it'll need to involve catching signals to some degree.
The problem with catching signals is, well, everything involved in catching signals. Either youâre handling them in a context thatâs very limited (POSIX allows me to write to a file here, but does Foundationâs implementation?), or youâre waking up another thread. Neither is great.
Thereâs definitely a code size concern here, and I see how compact crash info would help that. You could still get most of that benefit from a hypothetical swift_deriveFailureInfoFromReturnAddress or something, that did exception-table-like lookup before calling reportFatalError.
The main thing here is that âcustom handlingâ is at one end of the process and âwhat gets reported and howâ is at the other end, and they donât have to be designed together. Adding this functionality now does not preclude adding more laterâthough it does ratchet in anything currently using reportFatalError to keep providing that functionality. The perfect has been the enemy of the good for quite a while.
EDIT: I kind of donât want to put signal handling in this, because itâs much harder to distinguish whether a signal is a âsoft faultâ or a âhard faultâ. Signal handlers are also very limited to one per signal, and Iâm not sure Swift should claim that handler for this mechanism. Meanwhile, we know this kind of thing is useful, because of NSSetUncaughtExceptionHandler, mentioned in the very first post in this thread.
Yeah, I agree that signal handling is gross. Windows and Darwin have more composable alternatives, at leastâSEH is a natural fit to containing fault handling behavior to a scope, and Mach exception handling is gross but more flexible than signal handling. I know Linux has grown a few new mechanisms like signalfd (though AIUI that's targeted primarily toward asynchronous signals and not usually terminal signals like SIGSEGV/BUS/ILL/TRAP), but I don't know if there are yet more alternatives there these days.