Влияют ли функции, которые не определены как асинхронные, такие как mmap(2), на другие асинхронные функции, вызываемые в обработчике сигналов?

Я делаю библиотеку, которая внедряется в процессы и переопределяет некоторые функции, такие как open (2) для выполнения некоторых задач перед вызовом real open (2). Моя библиотека будет вызывать mmap (2). Поскольку open (2) асинхронно безопасен, возможно ли, что кто-то, использующий библиотеку, вызвал open (2) в обработчике сигналов, и где моя библиотека также добавила вызов mmap (2), мог сделать свой вызов open (2) ошибочным?

ОБНОВЛЕННЫЙ ВОПРОС:

void handle_sigint(int sig)
{
    int fd = open(“file”, O_RDWR, 0666);
    void *base = mmap(NULL, 20, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
}

В приведенной выше функции будет ли выполнен вызов open (2), потому что я вызвал mmap (2)?

2 ответа

Решение

Да.

Если ваш заменитель open() вызывает функцию, которая не безопасна для асинхронного сигнала, тогда для обработчика сигнала небезопасно вызывать вашу функцию. То, что оно имеет то же имя и сигнатуру, что и стандартная функция, безопасная для асинхронного сигнала, не имеет значения. То, что он вызывает замененную функцию или другие функции, безопасные для асинхронного сигнала, не имеет значения. То, что вызов потенциального обработчика сигнала в функцию, которая не является асинхронно-безопасной, не будет прямым, не имеет значения.

В ответ на обновление вопроса: если функция, представленная в вопросе, вызывается как обработчик сигнала, она имеет неопределенное поведение из-за вызова mmap(), Детали этого UB не могут быть предсказаны, по крайней мере, из соответствующих стандартов. Вот что значит "неопределенный". Нет никаких оснований полагать, что фактические и очевидные последствия open() звонок будет как-то защищен от помех. Ни общий механизм обработки сигналов. Ни чего другого в программе.

Чем дальше вы получаете от локуса UB, тем менее вероятен какой-либо заметный эффект, и тем более вероятно, что ОС будет его содержать, но UB не с чем связываться. В принципе, это может проявляться в любом поведении или поведении в пределах возможностей вашего компьютера, таких как стирание диска, отключение вентилятора ЦП или отправка пароля хакерам.

Это вполне возможно. Другим конфликтом может быть mmap(), работающий на main, который прерывается sighandler, который вызывает open(), который вызывает mmap(), вызывая повторный ввод mmap().

Главное ключевое слово здесь - "реентерабельный": любая функция, которую вы используете в sighandler, должна быть реентерабельной. Это означает, что функция манипулирует только данными стека или, если она манипулирует глобальными данными или состоянием, она должна делать это атомарным образом. Атомность - ужасно трудное достижение, которое сопровождается еще более ужасными побочными эффектами, которые необходимо обрабатывать (например, взаимоблокировки, необходимость поведения отката / перезапуска... Если у вас есть опыт работы с RDB, вы должны знать). В этом контексте mmap() является источником проблем, поскольку он не только манипулирует статическими данными процесса, но и обрабатывает статические данные.

Другие вопросы по тегам