Aside from the signal-based way of sampling call stacks, which is slow and unreliable on iOS/macOS, there is another, more effective way to do call stack sampling, with low-level mach calls. The basic strategy is:
Suspend the thread by calling thread_suspend
Collect a stack trace
Resume the thread with thread_resume
This strategy is used with success for stack sampling by Sentry and ETTrace. ETTrace's version can be seen in https://github.com/EmergeTools/ETTrace/blob/main/ETTrace/Tracer/EMGTracer.mm . Note that the stack trace unwinding can safely be done with frame pointers to reduce overhead, as opposed to the slower DWARF method, because Apple mandates that binaries don't omit frame pointers. It would be great to have call stack sampling on these platforms with this method, which I've found quite reliable and helpful (I am the original author of ETTrace's implementation of it).
Aside from the signal-based way of sampling call stacks, which is slow and unreliable on iOS/macOS, there is another, more effective way to do call stack sampling, with low-level mach calls. The basic strategy is:
thread_suspend
thread_resume
This strategy is used with success for stack sampling by Sentry and ETTrace. ETTrace's version can be seen in https://github.com/EmergeTools/ETTrace/blob/main/ETTrace/Tracer/EMGTracer.mm . Note that the stack trace unwinding can safely be done with frame pointers to reduce overhead, as opposed to the slower DWARF method, because Apple mandates that binaries don't omit frame pointers. It would be great to have call stack sampling on these platforms with this method, which I've found quite reliable and helpful (I am the original author of ETTrace's implementation of it).