Multiprocessing.Process Daemonic Behavior

MRAB python at mrabarnett.plus.com
Tue Mar 15 22:54:57 EDT 2011


On 16/03/2011 02:34, John L. Stephens wrote:
> Greetings,
>
> I'm trying to understand the behavior of the multiprocessing.Process
> daemonic attribute.
>
> Based on what I have read, if a Process ( X ) is created, and before it
> is started ( X.start() ), I should be able to set the process as
> daemonic using X.daemon=True.
>
> Once this attribute is set, if the parent process terminates, all
> daemonic process should also terminate.
>
> To experiment with this, I have written the following script.
> #-- BEGIN SCRIPT --#
> #!/usr/bin/env python
>
> from time import sleep
> from os import getpid
> from multiprocessing import Process
>
> class worker(Process):
> def __init__(self, id):
> Process.__init__(self)
> self.id = id
>
> def run(self):
> try:
> print 'Starting thread %s (pid:%s)' % (self.id, getpid())
> while True:
> print 'Hello from thread %s (pid:%s)' % (self.id, getpid())
> sleep(1)
> except KeyboardInterrupt:
> print '****** KeyboardInterrupt captured. Shutting down thread %d
> (pid:%s) ' % (self.id, getpid())
>
> if __name__ == '__main__':
> print 'Starting main (pid:%s)' % ( getpid())
> t = []
> try:
> for i in range(2):
> w = worker(i)
> w.daemon=True
> if w._daemonic: print 'thread %d is daemonic' % i
> t.append(w)
> try:
> for i in range(len(t)):
> t[i].start()
> loop = True
> while loop:
> loop = False
> for i in range(len(t)):
> if t[i].is_alive(): loop = True
> if not t[i]._daemonic: print 'thread %d is NOT daemonic' % i
> sleep(1)
> except KeyboardInterrupt: raise
> except KeyboardInterrupt:
> print 'KeyboardInterrupt captured. Shutting down main (pid:%s)' % getpid()
>
> print 'Shutting down'
> sleep(10)
> print 'Done.'
> # -- END SCRIPT -- #
>
>  From the command line, if I run the script and then enter ctrl-C the
> program and daemonic children terminate as I would expect.
> ~/temp$ ./threadtest.py
> Starting main (pid:13395)
> thread 0 is daemonic
> thread 1 is daemonic
> Starting thread 0 (pid:13396)
> Hello from thread 0 (pid:13396)
> Starting thread 1 (pid:13397)
> Hello from thread 1 (pid:13397)
> Hello from thread 0 (pid:13396)
> Hello from thread 1 (pid:13397)
> Hello from thread 0 (pid:13396)
> Hello from thread 1 (pid:13397)
> Hello from thread 0 (pid:13396)
> Hello from thread 1 (pid:13397)
> Hello from thread 0 (pid:13396)
> Hello from thread 1 (pid:13397)
> ^C
> KeyboardInterrupt captured. Shutting down main (pid:13395)
> Shutting down
> ****** KeyboardInterrupt captured. Shutting down thread 0 (pid:13396)
> ****** KeyboardInterrupt captured. Shutting down thread 1 (pid:13397)
> Done.
>
> Likewise, if i use a 'kill -2 13395', the results are the same (13395
> being the parent pid).
> If I use a 'kill -2 13396 13397', the daemonic children terminate, and
> the main closes as one would expect (13396 and 13397 being the children
> pids).
>
> However, if I use a 'kill 13395' (or something other then a SIGINT) the
> parent process terminates and the daemonic children CONTINUE TO PROCESS.
> The children essentially become zombies merrily meandering around the
> system. Really, is there anything worse then a daemonic zombie?
>
> I would have expected the daemonic children processes to terminate with
> the parent process, regardless of how the parent process terminates,
> either normally or forcefully.
>
> I would love to be enlightened....
>
At a guess I'd say that when the parent process terminates normally (of
its own accord) or is told to quit (SIGINT) it terminates its daemonic
children, but it's just killed (SIGKILL or uncaught signal) then it's
just stopped dead.



More information about the Python-list mailing list