Why daemon program does not exit without connection ()

The answer may be right in front of me at the link below, but I still do not understand. I'm sure that after someone explains this to me, Darwin will call me.

An example from this link is here , although I made some changes to try to experiment and help my understanding.

Here is the code:

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() 

And the code output:

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

If the connection () is uncommented at the end, then the output:

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

I'm confused. b / c sleep demon is 2 seconds and non-demon is 6 seconds. Why doesn't he print the "Exit" message in the first case? The demon had to wake up in front of a non-demon and type a message.

The explanation from the site is as follows:

The output does not include the message β€œExit” from the process daemon, since all non-demon processes (including the main program) before the daemon process wakes up from 2 seconds sleep.

but I changed it so that the demon had to wake up before the non-demon. What am I missing here? Thanks in advance for your help.

EDIT: Forgot to mention that I am using python 2.7, but apparently this problem is also in python 3.x

+5
source share
1 answer

It was fun to track. Documents are somewhat misleading because they describe processes without a daemon, as if they were all equivalent; the existence of any non-demonic process means that the "family" process is alive. But this is not how it is implemented. The parent process is more equal than others; multiprocessing registers the atexit handler, which performs the following actions:

 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() 

So, when the main process ends, it first terminate all daemon child processes, then join all child processes wait for non daemon children and clear resources from daemon children.

Since it performs cleaning in this order, a moment after the non daemon Process starts s, the main process starts cleaning and forcibly terminate daemon Process .

Note that fixing this can be as simple as join process not daemon manually, not just the join process of daemon (which completely breaks the whole daemon point); which prevents the atexit handler from being called, delaying the cleanup that will terminate child of daemon .

This may be a mistake (the one that seems to exist through 3.5.1, I have proven myself), but can it be a behavior error or an error in the documents.

+4
source

Source: https://habr.com/ru/post/1245671/


All Articles