В Проверке вопроса о Переполнении стека, если программа существует от удара, пишут сценарий принятого ответа, отмечает, что закрытие 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, просто разлетелось на whoknowwhere .
Еще более захватывающие, *файловые дескрипторы наследуются на fork()
. Это означает, что каждый детский процесс также будет иметь возможность писать где-то неожиданно. Хуже того, даже "безопасные" стратегии форкинга, например, когда все fds закрываются до exec
, обычно не трогают fds 0, 1 или 2. Так что Ваш маленький брейк почти наверняка переживет обычные стратегии, предназначенные для предотвращения катастроф через границы процесса.
Вы можете сказать: "Ну, тогда я никогда не буду использовать библиотеку, которая пишет в stderr, и я буду осторожен, никогда не пишу в stderr сам". На это у меня есть две вещи:
Друзья не позволяют друзьям закрывать stderr. Уомбл вон. бросает микрофон
Это может быть очень-очень плохо и привести к неопределенному поведению. Проверьте мой старый вопрос: Репликация MySQL прекращается после поворота binlog.
Мы закрыли fd 2 для демона mysql и в binlog.info было записано справочное сообщение. Это сломало репликацию "мастер-ведомый".