2016-05-23 10 views
1

В моей программе я замораживание иногда при записи стандартный вывод в данном случае: начинаетсяЗамораживания при записи `stderr`

  1. программы (например, из терминала)
  2. вилка программы самих два раза и с помощью execvp для запуска каждого процесса с различными параметрами (исходный файл считывается с /proc/self/exe)
  3. Первая запущенная программа завершается.
  4. Теперь два раздвоенный процессы все еще работают
  5. Закройте терминал первая программа была начата
  6. Несколько попыток использования fprintf писать stderr работы, на какой-то момент я получу полную блокировку на моей программе. Отладчик сообщает мне свой fprintf.

Что здесь происходит? Я уже пробовал поставить SIG_IGN на SIGPIPE, чтобы предотвратить сбой программы, как только никто больше не слушает трубы. Но теперь я застрял (поведение с замораживанием такое же, с SIG_IGN и без него).

Любая помощь приветствуется.

+2

_Questions, ищущие помощь по отладке («почему этот код не работает?») Должен включать в себя желаемое поведение, конкретную проблему или ошибку и кратчайший код, необходимый для воспроизведения в самом вопросе. Вопросы без четкого описания проблемы не полезны другим читателям. См.: Как создать минимальный, полный и проверенный пример ._ –

+0

Вопрос уже дан. – Nidhoegger

+0

Правильно, но все же, это должно быть полезно будущим читателям. Пояснение не требуется, ИМХО. –

ответ

3

В двух словах: система посылает ваши программные сигналы, чтобы избавить вас от проблемы. Вы игнорируете эти сигналы. Плохие вещи случаются.

Когда ваша родительская программа была запущена, она имела stdin (fd 0), stdout (fd 1) и stderr (fd 2), подключенные к TTY оболочки, которая запускала вас (терминал). Они очень похожи на трубы. Когда вы закрываете терминал, эти fds остаются висящими, и никто с другой стороны не может общаться с ними.

Сначала ничего плохого не происходит. Вы пишете stderr, а стандартная библиотека кэширует эти записи. Системные вызовы не выполняются, поэтому проблем нет.

Но тогда буферы заполняются, и stdlib пытается их смыть. Когда он это делает, он заполняет буферы ядра для канала или TTY. Сначала это прекрасно работает. Рано или поздно, однако, эти буферы также заполняются. Когда это произойдет, ядро ​​приостанавливает ваши процессы и ждет, когда кто-то прочитает с другого конца этих труб. Однако, поскольку вы закрыли терминал, никто никогда не будет, и ваши программы будут приостановлены на неопределенный срок.

Стандартный способ избежать этой проблемы - отключить дескрипторы файла 0-2 из управляющего TTY. Вместо того, чтобы рассказывать вам, как это сделать, я хотел бы предложить, что вы пытаетесь сделать здесь, запустить программу, чтобы она полностью отключилась от TTY, имеет имя: daemonizing.

Отъезд this вопрос для получения дополнительной информации о том, как это сделать.

Edited добавить:

Это было не ясно из вашей функции ли программы, вы execve ИНГ ваши собственные или нет. Если это не так, помните, что многие пользовательские программы не предназначены для работы в качестве демона. Наиболее очевидным является то, что если программа, не связанная с каким-либо TTY, открывает файл TTY, и если он не передает O_NOCTTY в open, TTY становится управляющим TTY программы. В зависимости от обстоятельств это может привести к неожиданным результатам.

+0

Большое спасибо, это объяснение мне очень помогло. То, что я хотел сделать в любом случае, - это войти в файл. Выход из системы на терминал во время разработки является временным. Я предполагаю, что это знак теперь, чтобы сделать журнал программы в файл вместо :). Большое спасибо! – Nidhoegger

+0

@Nidhoegger, если вы пишете файл с 'fprintf (stderr, ...)', будьте в курсе семантики. Если функции stdio видят, что назначение не является TTY, они будут очищаться, когда внутренние буферы заполнены, а не когда они видят EOL ('\ n'). В зависимости от вашего случая это может быть или не быть тем, что вы хотите. –

+0

* Вы пишете stderr, а стандартная библиотека кэширует эти записи. * Не обязательно. 'stderr' обычно полностью не загружается. Прикрепление 'strace' к текущему процессу почти наверняка покажет системные вызовы, сделанные в fd 2. –

 Смежные вопросы

  • Нет связанных вопросов^_^