| 73 | |
| 74 | |
| 75 | def daemonize(): |
| 76 | # Try to open the pidfile prior to forking. If there is a problem, |
| 77 | # the client can then exit with a proper exit status code and |
| 78 | # message. |
| 79 | try: |
| 80 | outfd = os.open(_pidname, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o666) |
| 81 | except PermissionError: |
| 82 | # User will have to look in syslog for error message since |
| 83 | # --daemon implies --syslog, all output gets redirected to |
| 84 | # syslog. |
| 85 | raise Fatal("failed to create/write pidfile %s" % _pidname) |
| 86 | |
| 87 | # Create a daemon process with a new session id. |
| 88 | if os.fork(): |
| 89 | os._exit(0) |
| 90 | os.setsid() |
| 91 | if os.fork(): |
| 92 | os._exit(0) |
| 93 | |
| 94 | # Write pid to the pidfile. |
| 95 | try: |
| 96 | os.write(outfd, b'%d\n' % os.getpid()) |
| 97 | finally: |
| 98 | os.close(outfd) |
| 99 | os.chdir("/") |
| 100 | |
| 101 | # Normal exit when killed, or try/finally won't work and the pidfile won't |
| 102 | # be deleted. |
| 103 | signal.signal(signal.SIGTERM, got_signal) |
| 104 | |
| 105 | si = open(os.devnull, 'r+') |
| 106 | os.dup2(si.fileno(), 0) |
| 107 | os.dup2(si.fileno(), 1) |
| 108 | si.close() |
| 109 | |
| 110 | |
| 111 | def daemon_cleanup(): |