Функция называется реентерабельной, если ее можно безопасно (и без побочных эффектов) вызвать в процессе выполнения.
Некоторые однопоточные приложения могут работать с нереентерабельными функциями. Потому что большинство приложений вообще не обрабатывают сигналы и не имеют рекурсивных функций обратного вызова. Будет сложно отладить код, если вы загрузите его в ядро Linux в виде модуля или во встроенной системе.
В этом коде функция calculate не является реентерабельной. Потому что функция calculate может быть вызвана сразу после выполнения расчета (строка номер 7) и устанавливает значение переменной sum. Однако в этом коде это не представляется возможным. Таким образом, даже с нереентерабельной функцией этот код все еще жизнеспособен.
Запустим:

Давайте обработаем сигнал Linux, SIGINT в коде:
Каждый раз, когда в этот код отправляется сигнал SIGINT (Ctrl + C), будет вызываться функция signal_handler. Обратите внимание, что функция signal_handler создает переменную с именем sum_internal.
Запустим:

Кажется, он работает нормально.
Я изменю функцию signal_handler. Функция signal_handler изменяет глобальную переменную sum:
Давайте проверим это:

Поскольку переменная sum является глобальной, при отправке сигнала SIGINT функция signal_handler изменяет ее. Мы представляем вызов функции с интенсивным вводом-выводом в функции calculate.
Во-первых, функция calculate вызывается функцией main (3 + 5). Кстати, я отправил программе сигнал SIGINT. Глобальная переменная sum была изменена. Поэтому мы видим на мгновение следующую строку:
Result from main: 110
Проблема в том, что функция calculate не является реентерабельной. Мы можем исправить код следующим образом:
Вроде нормально:

Иногда невозможно изменить реентерабельные функции. Потому что они являются частью glibc или частью сторонней библиотеки. Вы можете заблокировать сигнал при выполнении реентерабельной функции и разблокировать сигнал, когда закончите с реентерабельной функцией:
Запустим:

Нам удалось решить проблему, так как это был простой код. Представьте, что компилятор предупреждает вас, когда вы пытаетесь изменить глобальную переменную.
Попробуем написать такой же нереентерабельный код на Rust:
Rust заставит вас использовать глобальные переменные в блоке unsafe. Вы можете понять, что здесь что-то подозрительно.
Почему функции malloc() и printf() не являются реентерабельными?
https://stackoverflow.com/questions/3941271/why-are-malloc-and-printf-said-as-non-reentrant
Какие функции можно безопасно использовать?
https://manpages.ubuntu.com/manpages/bionic/man7/signal-safety.7.html
P.S.: strtok раньше была нереентерабельной функцией. Поэтому в glibc был добавлен strtok_r. Однако на момент этой фиксации strtok является оболочкой для strtok_r