I'm trying to find resources talking about handling synchronous signals (SIGSEGV, SIGILL etc.) compared to handling async signals.
The typical signal handling mechanism (using kill, for example) invokes signal handlers on control transfer from kernel to user mode. My understanding is that a 'synchronous' signal works more like a system call in that control transfers to kernel immediately - probably because synchronous signals are typically associated with CPU interrupts (memory protection etc.) and the kernel handler gets invoked for these anyway.
Are libc functions which are otherwise 'async-signal-unsafe' safe to be used in synchronous signal handlers? I see the Linux mprotect(2) man page uses printf inside a SIGSEGV handler, for example. How can I determine if a function can be used in these situations?
How does a typical Unix-like kernel's handling of synchronous signals differ from its handling of async signals? What makes them 'synchronous'?