2016-03-24 2 views
5

Ответ может быть прямо передо мной по ссылке ниже, но я до сих пор не понимаю. Я уверен, что после того, как кто-то объяснит это мне, Дарвин позвонит мне.Почему программа демон не выходит без соединения()

Пример at this link here, хотя я сделал некоторые изменения, чтобы попытаться поэкспериментировать и помочь понять.

Вот код:

import multiprocessing 
import time 
import sys 

def daemon(): 
    p = multiprocessing.current_process() 
    print 'Starting: ', p.name, p.pid 
    sys.stdout.flush() 
    time.sleep(2) 
    print 'Exiting: ', p.name, p.pid 
    sys.stdout.flush() 

def non_daemon(): 
    p = multiprocessing.current_process() 
    print 'Starting: ', p.name, p.pid 
    sys.stdout.flush() 
    time.sleep(6) 
    print 'Exiting: ', p.name, p.pid 
    sys.stdout.flush() 

if __name__ == '__main__': 
    d = multiprocessing.Process(name='daemon', target=daemon) 
    d.daemon = True 

    n = multiprocessing.Process(name='non-daemon', target=non_daemon) 
    n.daemon = False 

    d.start() 
    time.sleep(1) 
    n.start() 
# d.join() 

И выход код:

Starting: daemon 6173 
Starting: non-daemon 6174 
Exiting: non-daemon 6174 

Если присоединиться() на конец раскомментировать, то выход:

Starting: daemon 6247 
Starting: non-daemon 6248 
Exiting: daemon 6247 
Exiting: non-daemon 6248 

Я смущен b/c спать демона составляет 2 секунды, тогда как не-демон составляет 6 секунд. Почему он не распечатывает сообщение «Выход» в первом случае? Демон должен был проснуться перед не-демоном и напечатать сообщение.

Объяснение с сайта как таковой:

Выходной сигнал не включает в себя «Выход» сообщение от процесса демона , так как все процессы не-демона (в том числе основной программы) выход до того, как процесс демона просыпается со своего 2-го сонья .

но я изменил его так, что демон должен был проснуться до того, как не-демон. Что мне здесь не хватает? Заранее спасибо за вашу помощь.

EDIT: Забыл упомянуть, я использую Python 2.7, но по-видимому, эта проблема также в питона 3.x

ответ

4

Это было весело, чтобы разыскать. Документы несколько вводят в заблуждение, поскольку они описывают процессы без демона, как будто они все эквивалентны; существование любого не-демонического процесса означает, что процесс «семья» жив. But that's not how it's implemented. Родительский процесс «более равен», чем другие; multiprocessing регистрирует atexit обработчика, который выполняет следующие действия:

for p in active_children(): 
    if p.daemon: 
     info('calling terminate() for daemon %s', p.name) 
     p._popen.terminate() 

for p in active_children(): 
    info('calling join() for process %s', p.name) 
    p.join() 

Так что, когда основной процесс заканчивается, то его первыхterminate все, daemon дочерних процессов, затемjoin s всех дочерних процессов ждать не- daemon детей и очистить ресурсы от daemon детей.

Поскольку он выполняет очистку в таком порядке, момент после ваших не- daemonProcessstart с, основной процесс начинается очистка и принудительно terminate х годов daemonProcess.

Обратите внимание, что крепление это может быть так просто, как join ING в не- daemon процесс вручную, а не только join ING в daemon процесс (который побеждает весь смысл в daemon полностью); что предотвращает вызов обработчика atexit, задерживая очистку, которая будет terminatedaemon.

Возможно, это ошибка (кажется, что существует через 3.5.1, я сам себя зарекомендовал), но может ли это ошибка поведения или ошибка в документах.

+2

Я решил, что это является ошибкой, так как поведение отличается от 'threading' (который« мультипроцессор »должен эмулировать с использованием процессов вместо потоков), где потоки демона продолжают работать, пока поток _any_ non-daemon остается в живых (main или иным образом). Открыт [ошибка # 26633] (https://bugs.python.org/issue26633). – ShadowRanger

+0

thx для рассмотрения выше и выше при исследовании этой проблемы. Рад слышать, что я не сумасшедший, и Дарвин не будет призывать меня, по крайней мере на этот раз =) – Classified