Назад | Перейти на главную страницу

Опасности закрытия файловых дескрипторов

В вопросе о переполнении стека Проверьте, существует ли программа из сценария bash в принятый ответ отмечает, что закрытие stderr опасно:

(небольшое примечание: некоторые предложат 2> & - то же самое 2> / dev / null, но короче - это неверно. 2> & - закрывает FD 2, что вызывает ошибку в программе при попытке записи в stderr , что сильно отличается от успешной записи в него и отбрасывания вывода (и опасно!))

Да, это будет ломать вещи захватывающими и интересными способами.

Проблема в том, что Unix-подобные системы обычно выделяют файловые дескрипторы последовательно. Когда программе нужен новый дескриптор файла (т.е. они вызывают open(), socket(), и любую другую функцию, которая выделяет fd) ядро ​​найдет «свободный» дескриптор с наименьшим номером и передаст его.

Теперь представьте, если хотите, что вы закрыли fd 2 (stderr). Затем что-то в процессе требует дескриптора файла (следующего открытого файла). Ядро ищет свободный fd, видит, что fd 2 не используется, и возвращает его программе.

Теперь представьте, что что-то еще в программе хочет записать в stderr. Он слепо пишет в fd 2, потому что там живет stderr. Но сейчас это не так. Если ты счастливый, fd 2 был открыт только для чтения, и при записи возникает ошибка. Все предполагают, что запись в stderr всегда будет успешной, так что это будет весело. По крайней мере, не менее вероятно, что fd предназначен для чтения-записи (пять из шести fopen(2) режимы разрешены для записи - r+, a, a+, w, или w+), а сообщение, которое должно было быть отправлено на stderr, только что попало в кто знает где.

Что еще более интересно, * файловые дескрипторы наследуются fork(). Что означает, что каждый дочерний процесс также будет иметь возможность рисовать где-нибудь неожиданно. Хуже того, даже «безопасные» стратегии разветвления, например, когда все ФД закрываются раньше exec, как правило, не касайтесь fds 0, 1 или 2. Таким образом, ваша небольшая поломка почти наверняка переживет обычные стратегии, предназначенные для предотвращения сбоя через границы процесса.

Вы можете сказать: «Я никогда не буду использовать библиотеку, которая записывает в stderr, и я буду осторожен, чтобы никогда не писать в stderr сам». На это мне нужно сказать две вещи:

  1. Будущее - не будьте так осторожны. Вы забудете, что закрыли stderr.
  2. Все еще кто, возможно, когда-либо имел несчастье иметь дело с вашим сумасшедшим кодом, тоже не будет так осторожен.

Друзья не позволяют друзьям закрывать stderr. Вылезай. капает микрофон

Это может быть очень-очень плохим и вести к неопределенному поведению. Проверьте мой старый вопрос: Репликация MySQL завершается после ротации binlog.

Мы закрыли fd 2 для демона mysql, а справочное сообщение было записано в binlog.info. Это нарушило репликацию главный-подчиненный.