В Python родительский процесс продолжает существовать до тех пор, пока выполняются любые не-демонические дочерние процессы - PullRequest
0 голосов
/ 31 января 2019

Я использую многопроцессорный модуль Python.Я тестирую следующий код:

from multiprocessing import *
from time import sleep

def f():
    print ('in child#1 proc')
    sleep(2)
    print('ch#1 ends')

def f1() :
    print ('in child#2 proc')
    sleep(10)
    print('ch#2 ends')


if __name__ == '__main__':
    p = Process(target=f)
    p1 = Process(target=f1, daemon=True)
    p.start()
    p1.start()
    sleep(1)

    print ('child procs started')

У меня есть следующие наблюдения:

  • Первый дочерний процесс p выполняется в течение 2 секунд
  • После 1сек, второй дочерний процесс p1 становится зомби
  • Родительский (основной) процесс работает (активен) до тех пор, пока не будет запущен дочерний процесс № 1 (не-демон), то есть для 2secs

Теперь у меня есть следующие запросы:

  • Почему родительский (основной) процесс должен быть активным после завершения выполнения?Обратите внимание, что родитель не выполняет join на p.
  • Почему ребенок-демон p1 должен стать зомби через 1 секунду?Обратите внимание, что родительский (основной) процесс фактически остается активным до тех пор, пока не будет запущено p.

Я выполнил вышеупомянутую программу в Ubuntu.Мои наблюдения основаны на выводе команды ps на ubuntu

Ответы [ 2 ]

0 голосов
/ 31 января 2019

Чтобы подвести итог и продолжить обсуждение в комментариях к другому ответу:

Почему родительский (основной) процесс должен быть активным после завершения выполнения?Обратите внимание, что родитель не выполняет join для p.

multiprocessing, чтобы убедиться, что ваши программы, использующие его, работают хорошо.То есть он пытается убирать за собой.Для этого используется модуль atexit, который позволяет регистрировать обработчики выхода, которые должны выполняться, когда процесс интерпретатора готовится завершиться нормально.
multiprocessing определяет и регистрирует функцию_exit_function, который сначала вызывает terminate() для всех все еще работающих демонических потомков, а затем вызывает join() для всех оставшихся недемонических дочерних объектов.Так как join() блоков, родитель ждет, пока не-демонические дочерние элементы будут завершены.terminate(), с другой стороны, не блокирует, он просто отправляет сигнал SIGTERM (в Unix) childs и возвращает.

Это приводит нас к:

Почему ребенок-демон p1 должен стать зомби через 1 секунду?Обратите внимание, что родительский (основной) процесс фактически остается активным до тех пор, пока не будет запущено p.

Это потому, что родительский процесс достиг конца своих инструкций, и интерпретатор готовится завершить его, т.е.выполняет зарегистрированные обработчики выхода.Демон-ребенок p1 получает сигнал SIGTERM.Поскольку SIGTERM разрешено отлавливать и обрабатывать внутри процессов, дочернему элементу не приказано немедленно завершать работу, но вместо этого ему предоставляется возможность выполнить некоторую собственную очистку.Вот что заставляет p1 отображаться как <defunct>.Ядро знает, что процесс получил команду на завершение, но процесс еще не сделал этого.
В данном случае у p1 еще не было возможности выполнить сигнал SIGTERM, возможно потому, что он все ещевыполняет sleep().По крайней мере, начиная с Python 3.5 :

Теперь функция спит не менее секунд , даже если сон прерывается сигналом, за исключением случая, когда обработчик сигналавозникает исключение (см. PEP 475 для обоснования).

0 голосов
/ 31 января 2019

Родитель остается живым, потому что это корень приложения.Это остается в памяти, пока дети обрабатывают.Обратите внимание, что join ожидает выхода дочернего элемента, а затем возвращает управление родительскому элементу.Если вы не присоединитесь, родитель выйдет, но останется в памяти.

p1 будет зомби, потому что родитель выходит после сна 1. Он остается в живых с p, потому что вы не отключили p.если вы не отключили процесс и вызвали start для него, управление передается дочернему элементу, и когда дочерний процесс завершается, он передает управление обратно родителю.если вы сделаете это, он сохранит контроль над родителем, а потом запустит ребенка сзади.

...