forking and avoiding zombies!

peter pjmakey2 at gmail.com
Mon Dec 10 12:00:47 EST 2012


On 12/10/2012 12:42 PM, andrea crotti wrote:
> 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
Ou. yo need to use something more advanced. This is the code from book 
('Unix Network Programing' - the python implementation)

import sys, os
def daemonize (stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
     # Perform first fork.
     try:
         pid = os.fork( )
         if pid > 0:
             sys.exit(0) # Exit first parent.
     except OSError, e:
         sys.stderr.write("fork #1 failed: (%d) %s\n" % (e.errno, 
e.strerror))
         sys.exit(1)
# Decouple from parent environment.
     os.chdir("/")
     os.umask(0)
     os.setsid( )
# Perform second fork.
     try:
         pid = os.fork( )
         if pid > 0:
             sys.exit(0) # Exit second parent.
     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.
     for f in sys.stdout, sys.stderr: f.flush( )
     si = file(stdin, 'r')
     so = file(stdout, 'a+')
     se = file(stderr, 'a+', 0)
     os.dup2(si.fileno( ), sys.stdin.fileno( ))
     os.dup2(so.fileno( ), sys.stdout.fileno( ))
     os.dup2(se.fileno( ), sys.stderr.fileno( ))

Put this file and named daemon.py, then just for your program by calling 
import this file.

Like this.

from daemon import daemonize

def main():
       while True:
             print 'I'm Alive :)'

if __name__ == '__main__':
     daemonize(stdout='/var/log/run_time.log', stderr='/var/log/error.log')
     main()




More information about the Python-list mailing list