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

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

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

  • Кроме ошибки в программе записи, что могли произойти другие опасные вещи?
  • Может использование 2> &-, потенциально повреждают программу записи (т.е. останавливают ее выполнение и не позволяют очистку)?
1
задан 23 May 2017 в 15:41
2 ответа

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

Проблема в том, что 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, просто разлетелось на whoknowwhere .

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

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

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

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

5
ответ дан 3 December 2019 в 16:45

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

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

1
ответ дан 3 December 2019 в 16:45

Теги

Похожие вопросы