Реентерабельность (или повторная входимость, от англ. reentrancy) — это фундаментальный термин в программировании, обозначающий свойство функции или участка кода, который можно безопасно вызывать повторно до того, как завершился его предыдущий вызов.
Простыми словами: это способность программы выполнять несколько задач одновременно, используя один и тот же участок кода, без риска запутаться в данных или выдать ошибку.
Как это работает на практике. Представьте, что программа работает на кухне и готовит блины по одному рецепту (рецепт — это код, а повар — поток процессора).Нереентерабельный код: Повар начинает готовить первый блин, но чтобы узнать, сколько сахара нужно насыпать, он делает пометку на самом рецепте. Вдруг на кухню забегает второй повар и начинает готовить по тому же рецепту. Он стирает старую пометку и пишет свою. В итоге первый блин испорчен.Реентерабельный код: Повар держит все промежуточные данные (сахар, молоко) в своей личной памяти. Два повара могут готовить по одному и тому же рецепту одновременно, не заглядывая в чужие миски и не портя друг другу блюда.
Главные условия реентерабельного кода
Чтобы функция стала реентерабельной, она должна строго соблюдать следующие правила:
Не использовать глобальные или статические переменные (потому что их значение может изменить другой процесс).
Работать только с теми данными, которые переданы в качестве аргументов, или с локальными переменными, созданными внутри функции (обычно они хранятся в стеке).
Не вызывать нереентерабельные функции.
Не модифицировать собственный код во время выполнения.
Зачем это нужно?
Реентерабельность критически важна в современных технологиях:
Многопоточность (Multithreading) - Позволяет разным потокам программы одновременно выполнять одну и ту же функцию, увеличивая скорость работы.
Обработка прерываний. Позволяет процессору отвлечься на срочную задачу (например, обработку клика мыши), а затем вернуться к выполнению той же функции, которая была прервана, без потери данных.
Важные нюансыРеентерабельность vs Потокобезопасность (Thread-safety): Это похожие, но разные понятия. Код является потокобезопасным, если он защищен от одновременного доступа из разных потоков (например, с помощью специальных блокировок)
, если он защищен от одновременного доступа из разных потоков (например, с помощью специальных блокировок — mutex). Однако код может быть реентерабельным и без всяких блокировок, если он просто написан без использования общих данных.
Уязвимости: В сфере кибербезопасности и Web3 (например, при написании смарт-контрактов для сетей вроде Ethereum) атаки на базе реентерабельности являются одной из самых частых и опасных угроз. Вредоносный код может «вернуться» в функцию до того, как закончилось её предыдущее выполнение, и, например, похитить средства.