2012/12/11 Jean-Michel Pichavant <jeanmic...@sequans.com>:
> ----- Original Message -----
>> So I implemented a simple decorator to run a function in a forked
>> process, as below.
>>
>> It works well but the problem is that the childs end up as zombies on
>> one machine, while strangely
>> I can't reproduce the same on mine..
>>
>> I know that this is not the perfect method to spawn a daemon, but I
>> also wanted to keep the code
>> as simple as possible since other people will maintain it..
>>
>> What is the easiest solution to avoid the creation of zombies and
>> maintain this functionality?
>> thanks
>>
>>
>> def on_forked_process(func):
>>     from os import fork
>>     """Decorator that forks the process, runs the function and gives
>>     back control to the main process
>>     """
>>     def _on_forked_process(*args, **kwargs):
>>         pid = fork()
>>         if pid == 0:
>>             func(*args, **kwargs)
>>             _exit(0)
>>         else:
>>             return pid
>>
>>     return _on_forked_process
>> --
>> http://mail.python.org/mailman/listinfo/python-list
>>
>
> Ever though about using the 'multiprocessing' module? It's a slightly higher 
> API and I don't have issues with zombie processes.
> You can combine this with a multiprocess log listener so that all logs are 
> sent to the main process.
>
> See Vinay Sajip's code about multiprocessing and logging, 
> http://plumberjack.blogspot.fr/2010/09/using-logging-with-multiprocessing.html
>
> I still had to write some cleanup code before leaving the main process, but 
> once terminate is called on all remaining subprocesses, I'm not left with 
> zombie processes.
> Here's the cleaning:
>
> for proc in multiprocessing.active_children():
>     proc.terminate()
>
> JM
>
>
> -- IMPORTANT NOTICE:
>
> The contents of this email and any attachments are confidential and may also 
> be privileged. If you are not the intended recipient, please notify the 
> sender immediately and do not disclose the contents to any other person, use 
> it for any purpose, or store or copy the information in any medium. Thank you.


Yes I thought about that but I want to be able to kill the parent
without killing the childs, because they can run for a long time..

Anyway I got something working now with this

def daemonize(func):

    def _daemonize(*args, **kwargs):
        # Perform first fork.
        try:
            pid = os.fork()
            if pid > 0:
                sys.exit(0) # Exit first parent.
        except OSError as e:
            sys.stderr.write("fork #1 failed: (%d) %s\n" % (e.errno,
e.strerror))
            sys.exit(1)

        # Decouple from parent environment.
        # check if decoupling here makes sense in our case
        # os.chdir("/")
        # os.umask(0)
        # os.setsid()

        # Perform second fork.
        try:
            pid = os.fork()
            if pid > 0:
                return pid

        except OSError, e:
            sys.stderr.write("fork #2 failed: (%d) %s\n" % (e.errno,
e.strerror))
            sys.exit(1)

        # The process is now daemonized, redirect standard file descriptors.
        sys.stdout.flush()
        sys.stderr.flush()
        func(*args, **kwargs)

    return _daemonize


@daemonize
def long_smarter_process():
    while True:
        sleep(2)
        print("Hello how are you?")


And it works exactly as before, but more correctly..
-- 
http://mail.python.org/mailman/listinfo/python-list

Reply via email to