上面这个方法可以监控到大部分的 Signal 非常,但是我们会发现如果遇到死循环这类的Crash,就没法监控了。缘故起因是一样寻常环境下,信号处理处罚函数被调用时,内核会在历程的栈上为其创建一个栈帧。但这里就会有一个题目,如果之前栈的增长到达了栈的最大长度,或是栈没有到达最大长度但也比力接近,那么就会导致信号处理处罚函数不能得到充足栈帧分配。
为相识决这个题目,我们必要设定一个可选的栈帧:
We still need to use signal handlers to catch SIGABRT in-process. The kernel sends an EXC_CRASH mach exception to denote SIGABRT termination. In that case, catching the Mach exception in-process leads to process deadlock in an uninterruptable wait. Thus, we fall back on BSD signal handlers for SIGABRT, and do not register forEXC_CRASH.
If you’re messing with EXC_CRASH, you probably know that a major drawback of this scheme is that it can only respond to crashes that originated as genuine hardware traps. abort() and all of the things that wind up calling abort() are not, they’re generated entirely in software. This is important for a crash reporter because lots of interesting crashes arise through this mechanism, such as assertion failures and runtime (C++ and Objective-C) exceptions. abort() is implemented in Libc-825.26/stdlib/FreeBSD/abort.c abort, and it raises SIGABRT all on its own, without ever triggering a hardware trap. That means that your program can catch these crashes in-process via the POSIX signal interface, but because it was never a Mach exception to begin with, there’s no opportunity to catch one.
This is where EXC_CRASH comes in. EXC_CRASH is a new (as of Mac OS X 10.5) exception type that’s only generated in one place: when a process is dying an abnormal death. In xnu-2050.24.15/bsd/kern/kern_exit.c proc_prepareexit, the logic says that if the process is exiting due to a signal that’s considered a crash (one that might generate a “ core” file, identified by the presence of SA_CORE in xnu-2050.24.15/bsd/sys/signalvar.h sigprop), an EXC_CRASH Mach exception will be raised for the task. Along with several other signals, the SIGILL, SIGSEGV, SIGBUS, and SIGABRT examples above are all core-generating, so they qualify for this treatment. By the time a process is exiting due to an unhandled signal, it’s a goner. It’s not going to be scheduled any more. That includes any Mach exception handler that was running on a thread in the process. This is why you can’t catch EXC_CRASHexceptions in the process itself: by the time an EXC_CRASH is generated, your process is no longer running. Indeed, in the bug report, you can see the abort() as an “upstream” caller of in-kernel process teardown code, passing through proc_prepareexit, exception_triage, and ultimately getting blocked waiting for a response to mach_exception_raise that will never come.