(I understand there are some existing questions on SO about the same topic and I have read top answers. Those answers are good but I still have something unclear.) Recently I came across a piece of Python for creating daemon process in Unix system: sample code And the piece I want to talk about:
def daemonize(self):
"""
do the UNIX double-fork magic, see Stevens' "Advanced
Programming in the UNIX Environment" for details (ISBN 0201563177)
http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16
"""
try:
pid = os.fork()
if pid > 0:
# exit first parent
sys.exit(0)
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.setsid()
os.umask(0)
# do second fork
try:
pid = os.fork()
if pid > 0:
# exit from second parent
sys.exit(0)
except OSError, e:
sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror))
sys.exit(1)
# redirect standard file descriptors
sys.stdout.flush()
sys.stderr.flush()
si = file(self.stdin, 'r')
so = file(self.stdout, 'a+')
se = file(self.stderr, 'a+', 0)
os.dup2(si.fileno(), sys.stdin.fileno())
os.dup2(so.fileno(), sys.stdout.fileno())
os.dup2(se.fileno(), sys.stderr.fileno())
# write pidfile
atexit.register(self.delpid)
pid = str(os.getpid())
file(self.pidfile,'w+').write("%s\n" % pid)
So the process is:
So is my understanding correct about the process of creating a daemon process? Also some people mentioned "this can prevent zombie processes" in SO question, why is this piece of code even related to zombie process? Parent will be killed so that the process is monitored by init, is not that what "daemon" means?
Some people also mention that forking once should give us a good daemon process already. Any example for this? Any example(system) under which fork once may not just work as a good daemon?
A process being part of same session means when bash receives SIGHUP when you disconnect over ssh, it terminates all the processes in the session. Default SIGHUP handler also terminates process. To avoid this you want to create a new session.
Additionally, TTY is a somewhat old concept, which through the years has picked up a huge history and loads of corner cases intended for interactivity, but are counterproductive when running daemons, because you do not want the kernel to send random signals to your non-interactive daemon process when something TTY related happens.
So ... you do not want to be a member of TTY session and you do not want to be a session leader, because those get signalled.
That's why you start a daemon: you run python1, this process forks, you get python1 and python2. Python2 starts new session and forks, so you get python3.
Setsid in python2 ensures python3 is not connected to python1 session, and fork in python2 is needed because python2 is still a session leader.
Python3 will then not receive any TTY related signals and won't be killed by SIGHUP when you disconnect or whatever TTY related stuff happens on the box.