use an empty OEMASK if none is set
[bitbake.git] / bin / utils / daemon.py
1 #!/usr/bin/python
2
3 '''
4         This module is used to fork the current process into a daemon.
5         Almost none of this is necessary (or advisable) if your daemon 
6         is being started by inetd. In that case, stdin, stdout and stderr are 
7         all set up for you to refer to the network connection, and the fork()s 
8         and session manipulation should not be done (to avoid confusing inetd). 
9         Only the chdir() and umask() steps remain as useful.
10         References:
11                 UNIX Programming FAQ
12                     1.7 How do I get my program to act like a daemon?
13                         http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16
14                 Advanced Programming in the Unix Environment
15                     W. Richard Stevens, 1992, Addison-Wesley, ISBN 0-201-56317-7.
16
17         History:
18           2001/07/10 by Jürgen Hermann
19           2002/08/28 by Noah Spurrier
20           2003/02/24 by Clark Evans
21           
22           http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66012
23 '''
24 import sys, os, time
25 from signal import SIGTERM
26
27 def daemonize(stdout='/dev/null', stderr=None, stdin='/dev/null', pidfile=None, startmsg=None):
28         ''' 
29                 This forks the current process into a daemon.
30                 The stdin, stdout, and stderr arguments are file names that
31                 will be opened and be used to replace the standard file descriptors
32                 in sys.stdin, sys.stdout, and sys.stderr.
33                 These arguments are optional and default to /dev/null.
34                 Note that stderr is opened unbuffered, so
35                 if it shares a file with stdout then interleaved output
36                 may not appear in the order that you expect.
37         '''
38         # Do first fork.
39         try: 
40                 pid = os.fork() 
41                 if pid > 0: sys.exit(0) # Exit first parent.
42         except OSError, e: 
43                 sys.stderr.write("fork #1 failed: (%d) %s\n" % (e.errno, e.strerror))
44                 sys.exit(1)
45                 
46         # Decouple from parent environment.
47         os.chdir("/") 
48         os.umask(0) 
49         os.setsid() 
50         
51         # Do second fork.
52         try: 
53                 pid = os.fork() 
54                 if pid > 0: sys.exit(0) # Exit second parent.
55         except OSError, e: 
56                 sys.stderr.write("fork #2 failed: (%d) %s\n" % (e.errno, e.strerror))
57                 sys.exit(1)
58         
59         # Open file descriptors and print start message
60         if not stderr: stderr = stdout
61         si = file(stdin, 'r')
62         so = file(stdout, 'a+')
63         se = file(stderr, 'a+', 0)
64         pid = str(os.getpid())
65         if startmsg:
66                 sys.stderr.write("\n%s\n" % startmsg % pid)
67                 sys.stderr.flush()
68         if pidfile: file(pidfile,'w+').write("%s\n" % pid)
69         
70         # Redirect standard file descriptors.
71         os.dup2(si.fileno(), sys.stdin.fileno())
72         os.dup2(so.fileno(), sys.stdout.fileno())
73         os.dup2(se.fileno(), sys.stderr.fileno())