import repository from arizona
[raven.git] / lib / ravenlib / daemon.py
1 import os
2 import sys
3 import syslog
4
5 import ravenlib.typecheck
6
7 def make_daemon(program):
8    """
9    <Purpose>
10       Turns the currently running program into a daemon, detaching it from
11       the console so that it runs in the background.
12
13    <Arguments>
14       program:
15               Filename (not including path) of the program being turned
16               into a daemon.  Used for logging, error reporting, and to
17               write the pid of the daemon to `/var/run/PROGRAM.pid'.
18
19    <Exceptions>
20       TypeError if a bad parameter is detected.
21
22    <Side Effects>
23       Terminates the program if the command fails.
24
25    <Returns>
26       pid of the daemon
27    """
28    # check params
29    ravenlib.typecheck.simple(program, "program", str, "make_daemon")
30
31    # log what we're about to do and fork
32    syslog.syslog("[" + program + "] Starting daemon...")
33    pid = os.fork()
34
35    # if fork was successful, exit the parent process so it returns
36    try:
37       if pid > 0:
38          os._exit(0)
39    except OSError:
40       syslog.syslog("[" + program + "] Error: fork failed, daemon not started")
41       sys.exit(1)
42
43    # Print my pid into /var/run/PROGRAM.pid
44    pid = str(os.getpid())
45    filename = "/var/run/" + program + ".pid"
46    try:
47       out_file = open(filename, "w")
48       out_file.write(pid)
49       out_file.close()
50    except IOError:
51       syslog.syslog("[" + program + "] IOError writing: " + filename)
52
53    # close any open files
54    try:
55       sys.stdin.close()
56    except:
57       syslog.syslog("[" + program + "] Error closing stdin")
58    try:
59       sys.stdout.close()
60    except:
61       syslog.syslog("[" + program + "] Error closing stdout")
62    try:
63       sys.stderr.close()
64    except:
65       syslog.syslog("[" + program + "] Error closing stderr")
66    for i in range(1023):
67       try:
68          os.close(i)
69       except OSError:
70          pass
71
72    # redirect stdin/out/err to /dev/null
73    try:
74       sys.stdin = open('/dev/null')       # fd 0
75    except:
76       syslog.syslog("[" + program + "] Error opening new stdin")
77    try:
78       sys.stdout = open('/dev/null', 'w') # fd 1
79    except:
80       syslog.syslog("[" + program + "] Error opening new stdout")
81    try:
82       sys.stderr = open('/dev/null', 'w') # fd 2
83    except:
84       syslog.syslog("[" + program + "] Error opening new stderr")
85
86    # disassociate from parent
87    os.chdir("/")
88    os.setsid()
89    os.umask(0)
90
91    return pid
92