Ответ 1
Существуют две потенциальные проблемы:
Внутри обработчика сигнала вы можете использовать только функции асинхронного безопасного вызова. Большинство функций не поддерживают безопасный сигнал.
Причиной ограничения является то, что функция может быть вызвана в середине выполнения одной и той же функции. Таким образом, внутреннее состояние может быть повреждено. Очень мало функций - это безопасный асинхронный сигнал, а все, что выделяет память динамически, - нет. В OCaml многие распределения происходят "за кулисами", поэтому вполне вероятно, что ваш код не будет безопасен для асинхронного сигнала.
В вашем случае вы вызываете функцию, которая записывает на стандартный вывод. В C это никогда не безопасно для асинхронного сигнала, за одним исключением: примитивная функция write()
. Это необработанный системный вызов (который работает с файловым дескриптором) и безопасен для асинхронного сигнала по той простой причине, что само ядро не заботится о том, что вы находитесь в обработчике сигналов, и полностью очистится, прежде чем возвращать управление вам.
Вызов небезопасной функции из обработчика сигнала, когда сигнал был асинхронным (случай здесь) и сам прервался, небезопасная функция - это поведение undefined в C. Это означает, что все может случиться - включая вашу программу, работающую правильно, но также включая ошибки сегментации или другие ошибки, а также позволяет злоумышленнику выполнить произвольный код. Обычно это связано с низкоуровневыми языками, такими как C, и это то, что обычно не встречается в OCaml.
OCaml использует аккуратный трюк: когда принимается сигнал, для которого обработчик установлен в OCaml, он откладывает выполнение обработчика до безопасного пункта. Результатом является то, что в обработчике безопасно установить количество незаполненных в переменную ref
. Однако другие функции, такие как print
, возможно, не являются реентерабельными, поскольку они могут иметь внутреннее состояние. В общем, в обработчике сигнала вы должны стараться избегать делать больше, чем устанавливать флаг и быстро возвращаться. В OCaml флаг должен быть 31- или 63-битным целым числом или логическим, потому что они распаковываются. В C флаг должен быть либо volatile sig_atomic_t
, либо (я не уверен в этом) атомным типом C11.
@TheCodeArtist дает другую возможную причину ошибки.