All signal handlers are calling non-async-safe functions, for example exit and fprintf. This is undefined behavior according to the C99 and POSIX standard. A list of async-safe functions can be found here: https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_04_03.
A potential bug is that glibc may have locked stderr in the main thread when the signal handler is called, leading to a deadlock when the signal handler calls fprintf.
Therefore, any output to stdout or stderr must either be delayed to run outside the signal handler context or be done using async-safe primitives like write.
Similarly, exit can be replaced by tcflush and _exit since netcat doesn't register any atexit handlers.
This behavior was detected using techniques developed by the SYMBIOSYS research project at COMSYS, RWTH Aachen University. This research is supported by the European Research Council (ERC) under the EU's Horizon 2020 Research and Innovation Programme grant agreement n. 647295 (SYMBIOSYS).