Linux, .NET/C#: после fork() родительский процесс завершается, когда дочерний процесс вызывает exec().Linux

Ответить
Anonymous
 Linux, .NET/C#: после fork() родительский процесс завершается, когда дочерний процесс вызывает exec().

Сообщение Anonymous »

Я пытаюсь написать код, размещающий дочерний процесс в PTY. Это не намного сложнее, чем просто перенаправление stdin и stdout, но в этом есть кое-что. Согласно документации:
  • Вы вызываете openpty, который находит свободный PTY и возвращает «главный» и «подчиненный» файловые дескрипторы для своего двунаправленного канала.
  • Вы разветвляете, создавая дочерний процесс.
  • В родительском процессе fork возвращает идентификатор дочернего процесса. Затем родительский процесс может читать из главного FD, чтобы наблюдать за выходными данными процесса, и записывать в него данные для отправки входных данных.
  • В дочернем процессе fork возвращает 0. Теперь дочернему процессу предстоит выполнить некоторые конкретные задачи:

    ФД stdin, stdout и stderr по умолчанию должны быть закрыты.
  • используется для вставки подчиненного FD из PTY в STDIN_FILENO, STDOUT_FILENO и STDERR_FILENO.
  • Наконец, вариант exec используется для замены дочернего процесса желаемой другой программой.

Управляемая среда .NET не очень совместима с этой последовательностью, поскольку существуют всевозможные потоки управления, такие как сбор мусора, а ответвление клонирует только поток, который его вызвал. Но я пишу код, основываясь на обнадеживающем предположении, что если я ограничусь прямыми простыми вызовами P/Invoke и избегаю маршалинга и исключений, то JIT-вывод, который необходимо выполнить, будет довольно простым и должен работать до тех пор, пока процесс не будет заменен.
Насколько я могу судить, это действительно так. По моим наблюдениям, вызовы P/Invoke для закрытия и dup2 между fork и exec работают нормально. Но как только дочерний процесс вызывает exec (я использую вариант execvp с аргументами, предварительно маршалируемыми перед fork на всякий случай), родительский процесс умирает. Я не вижу никакого объяснения; отладчик просто говорит: Программа «[3744333] QBX.dll» завершилась с кодом 0 (0x0).
Моя первоначальная мысль заключалась в том, что должны быть какие-то сигналы и каким-то образом родительский процесс их улавливает. Это, казалось, подтвердилось, когда я прочитал документацию в базе кода среды выполнения, в которой говорилось, что сигналы перехватываются с помощью крошечного обработчика-заглушки, который просто записывает уведомление о событии в канал, чтобы оно могло быть перехвачено потоком обработки сигналов в другом месте. Если дочерний процесс получает копию дескрипторов канала, то все, что он записывает, будет подхвачено родительским процессом.
Реализация SystemNative_ForkAndExecProcess во время выполнения содержит некоторый дополнительный код, который очищает обработчики сигналов перед разветвлением. Как ни странно, похоже, конфигурация восстанавливается после разветвления и перед exec. В любом случае я точно воспроизвел то, что делает SystemNative_ForkAndExecProcess, но мой родительский процесс все равно умирает, как только дочерний запускает exec. Если я заменю вызов exec из дочернего процесса на Environment.Exit, то у родительского процесса, очевидно, нет дочернего процесса для взаимодействия, но он также не закроется.
Как предотвратить выход родительского процесса, когда дочерний процесс вызывает exec? Это должно быть возможно, потому что это делает фреймворк.
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Linux»