annotate python-daemon-2.0.5/daemon/daemon.py @ 44:da86478b1d64

clean up strange tools that just a url linkout
author jingchunzhu <jingchunzhu@gmail.com>
date Mon, 27 Jul 2015 15:30:10 -0700
parents 7ceb967147c3
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
33
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
1 # -*- coding: utf-8 -*-
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
2
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
3 # daemon/daemon.py
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
4 # Part of ‘python-daemon’, an implementation of PEP 3143.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
5 #
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
6 # Copyright © 2008–2015 Ben Finney <ben+python@benfinney.id.au>
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
7 # Copyright © 2007–2008 Robert Niederreiter, Jens Klein
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
8 # Copyright © 2004–2005 Chad J. Schroeder
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
9 # Copyright © 2003 Clark Evans
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
10 # Copyright © 2002 Noah Spurrier
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
11 # Copyright © 2001 Jürgen Hermann
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
12 #
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
13 # This is free software: you may copy, modify, and/or distribute this work
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
14 # under the terms of the Apache License, version 2.0 as published by the
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
15 # Apache Software Foundation.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
16 # No warranty expressed or implied. See the file ‘LICENSE.ASF-2’ for details.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
17
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
18 """ Daemon process behaviour.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
19 """
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
20
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
21 from __future__ import (absolute_import, unicode_literals)
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
22
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
23 import os
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
24 import sys
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
25 import resource
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
26 import errno
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
27 import signal
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
28 import socket
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
29 import atexit
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
30 try:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
31 # Python 2 has both ‘str’ (bytes) and ‘unicode’ (text).
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
32 basestring = basestring
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
33 unicode = unicode
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
34 except NameError:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
35 # Python 3 names the Unicode data type ‘str’.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
36 basestring = str
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
37 unicode = str
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
38
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
39
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
40 class DaemonError(Exception):
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
41 """ Base exception class for errors from this module. """
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
42
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
43 def __init__(self, *args, **kwargs):
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
44 self._chain_from_context()
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
45
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
46 super(DaemonError, self).__init__(*args, **kwargs)
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
47
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
48 def _chain_from_context(self):
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
49 _chain_exception_from_existing_exception_context(self, as_cause=True)
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
50
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
51
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
52 class DaemonOSEnvironmentError(DaemonError, OSError):
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
53 """ Exception raised when daemon OS environment setup receives error. """
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
54
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
55
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
56 class DaemonProcessDetachError(DaemonError, OSError):
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
57 """ Exception raised when process detach fails. """
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
58
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
59
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
60 class DaemonContext:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
61 """ Context for turning the current program into a daemon process.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
62
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
63 A `DaemonContext` instance represents the behaviour settings and
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
64 process context for the program when it becomes a daemon. The
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
65 behaviour and environment is customised by setting options on the
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
66 instance, before calling the `open` method.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
67
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
68 Each option can be passed as a keyword argument to the `DaemonContext`
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
69 constructor, or subsequently altered by assigning to an attribute on
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
70 the instance at any time prior to calling `open`. That is, for
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
71 options named `wibble` and `wubble`, the following invocation::
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
72
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
73 foo = daemon.DaemonContext(wibble=bar, wubble=baz)
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
74 foo.open()
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
75
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
76 is equivalent to::
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
77
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
78 foo = daemon.DaemonContext()
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
79 foo.wibble = bar
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
80 foo.wubble = baz
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
81 foo.open()
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
82
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
83 The following options are defined.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
84
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
85 `files_preserve`
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
86 :Default: ``None``
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
87
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
88 List of files that should *not* be closed when starting the
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
89 daemon. If ``None``, all open file descriptors will be closed.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
90
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
91 Elements of the list are file descriptors (as returned by a file
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
92 object's `fileno()` method) or Python `file` objects. Each
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
93 specifies a file that is not to be closed during daemon start.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
94
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
95 `chroot_directory`
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
96 :Default: ``None``
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
97
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
98 Full path to a directory to set as the effective root directory of
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
99 the process. If ``None``, specifies that the root directory is not
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
100 to be changed.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
101
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
102 `working_directory`
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
103 :Default: ``'/'``
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
104
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
105 Full path of the working directory to which the process should
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
106 change on daemon start.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
107
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
108 Since a filesystem cannot be unmounted if a process has its
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
109 current working directory on that filesystem, this should either
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
110 be left at default or set to a directory that is a sensible “home
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
111 directory” for the daemon while it is running.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
112
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
113 `umask`
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
114 :Default: ``0``
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
115
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
116 File access creation mask (“umask”) to set for the process on
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
117 daemon start.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
118
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
119 A daemon should not rely on the parent process's umask value,
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
120 which is beyond its control and may prevent creating a file with
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
121 the required access mode. So when the daemon context opens, the
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
122 umask is set to an explicit known value.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
123
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
124 If the conventional value of 0 is too open, consider setting a
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
125 value such as 0o022, 0o027, 0o077, or another specific value.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
126 Otherwise, ensure the daemon creates every file with an
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
127 explicit access mode for the purpose.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
128
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
129 `pidfile`
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
130 :Default: ``None``
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
131
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
132 Context manager for a PID lock file. When the daemon context opens
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
133 and closes, it enters and exits the `pidfile` context manager.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
134
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
135 `detach_process`
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
136 :Default: ``None``
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
137
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
138 If ``True``, detach the process context when opening the daemon
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
139 context; if ``False``, do not detach.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
140
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
141 If unspecified (``None``) during initialisation of the instance,
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
142 this will be set to ``True`` by default, and ``False`` only if
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
143 detaching the process is determined to be redundant; for example,
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
144 in the case when the process was started by `init`, by `initd`, or
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
145 by `inetd`.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
146
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
147 `signal_map`
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
148 :Default: system-dependent
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
149
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
150 Mapping from operating system signals to callback actions.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
151
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
152 The mapping is used when the daemon context opens, and determines
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
153 the action for each signal's signal handler:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
154
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
155 * A value of ``None`` will ignore the signal (by setting the
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
156 signal action to ``signal.SIG_IGN``).
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
157
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
158 * A string value will be used as the name of an attribute on the
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
159 ``DaemonContext`` instance. The attribute's value will be used
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
160 as the action for the signal handler.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
161
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
162 * Any other value will be used as the action for the
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
163 signal handler. See the ``signal.signal`` documentation
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
164 for details of the signal handler interface.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
165
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
166 The default value depends on which signals are defined on the
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
167 running system. Each item from the list below whose signal is
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
168 actually defined in the ``signal`` module will appear in the
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
169 default map:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
170
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
171 * ``signal.SIGTTIN``: ``None``
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
172
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
173 * ``signal.SIGTTOU``: ``None``
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
174
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
175 * ``signal.SIGTSTP``: ``None``
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
176
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
177 * ``signal.SIGTERM``: ``'terminate'``
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
178
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
179 Depending on how the program will interact with its child
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
180 processes, it may need to specify a signal map that
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
181 includes the ``signal.SIGCHLD`` signal (received when a
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
182 child process exits). See the specific operating system's
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
183 documentation for more detail on how to determine what
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
184 circumstances dictate the need for signal handlers.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
185
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
186 `uid`
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
187 :Default: ``os.getuid()``
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
188
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
189 `gid`
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
190 :Default: ``os.getgid()``
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
191
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
192 The user ID (“UID”) value and group ID (“GID”) value to switch
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
193 the process to on daemon start.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
194
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
195 The default values, the real UID and GID of the process, will
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
196 relinquish any effective privilege elevation inherited by the
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
197 process.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
198
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
199 `prevent_core`
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
200 :Default: ``True``
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
201
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
202 If true, prevents the generation of core files, in order to avoid
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
203 leaking sensitive information from daemons run as `root`.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
204
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
205 `stdin`
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
206 :Default: ``None``
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
207
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
208 `stdout`
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
209 :Default: ``None``
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
210
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
211 `stderr`
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
212 :Default: ``None``
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
213
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
214 Each of `stdin`, `stdout`, and `stderr` is a file-like object
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
215 which will be used as the new file for the standard I/O stream
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
216 `sys.stdin`, `sys.stdout`, and `sys.stderr` respectively. The file
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
217 should therefore be open, with a minimum of mode 'r' in the case
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
218 of `stdin`, and mimimum of mode 'w+' in the case of `stdout` and
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
219 `stderr`.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
220
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
221 If the object has a `fileno()` method that returns a file
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
222 descriptor, the corresponding file will be excluded from being
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
223 closed during daemon start (that is, it will be treated as though
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
224 it were listed in `files_preserve`).
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
225
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
226 If ``None``, the corresponding system stream is re-bound to the
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
227 file named by `os.devnull`.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
228
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
229 """
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
230
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
231 __metaclass__ = type
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
232
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
233 def __init__(
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
234 self,
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
235 chroot_directory=None,
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
236 working_directory="/",
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
237 umask=0,
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
238 uid=None,
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
239 gid=None,
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
240 prevent_core=True,
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
241 detach_process=None,
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
242 files_preserve=None,
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
243 pidfile=None,
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
244 stdin=None,
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
245 stdout=None,
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
246 stderr=None,
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
247 signal_map=None,
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
248 ):
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
249 """ Set up a new instance. """
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
250 self.chroot_directory = chroot_directory
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
251 self.working_directory = working_directory
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
252 self.umask = umask
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
253 self.prevent_core = prevent_core
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
254 self.files_preserve = files_preserve
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
255 self.pidfile = pidfile
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
256 self.stdin = stdin
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
257 self.stdout = stdout
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
258 self.stderr = stderr
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
259
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
260 if uid is None:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
261 uid = os.getuid()
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
262 self.uid = uid
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
263 if gid is None:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
264 gid = os.getgid()
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
265 self.gid = gid
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
266
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
267 if detach_process is None:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
268 detach_process = is_detach_process_context_required()
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
269 self.detach_process = detach_process
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
270
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
271 if signal_map is None:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
272 signal_map = make_default_signal_map()
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
273 self.signal_map = signal_map
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
274
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
275 self._is_open = False
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
276
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
277 @property
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
278 def is_open(self):
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
279 """ ``True`` if the instance is currently open. """
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
280 return self._is_open
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
281
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
282 def open(self):
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
283 """ Become a daemon process.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
284
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
285 :return: ``None``.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
286
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
287 Open the daemon context, turning the current program into a daemon
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
288 process. This performs the following steps:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
289
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
290 * If this instance's `is_open` property is true, return
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
291 immediately. This makes it safe to call `open` multiple times on
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
292 an instance.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
293
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
294 * If the `prevent_core` attribute is true, set the resource limits
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
295 for the process to prevent any core dump from the process.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
296
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
297 * If the `chroot_directory` attribute is not ``None``, set the
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
298 effective root directory of the process to that directory (via
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
299 `os.chroot`).
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
300
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
301 This allows running the daemon process inside a “chroot gaol”
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
302 as a means of limiting the system's exposure to rogue behaviour
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
303 by the process. Note that the specified directory needs to
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
304 already be set up for this purpose.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
305
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
306 * Set the process UID and GID to the `uid` and `gid` attribute
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
307 values.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
308
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
309 * Close all open file descriptors. This excludes those listed in
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
310 the `files_preserve` attribute, and those that correspond to the
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
311 `stdin`, `stdout`, or `stderr` attributes.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
312
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
313 * Change current working directory to the path specified by the
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
314 `working_directory` attribute.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
315
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
316 * Reset the file access creation mask to the value specified by
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
317 the `umask` attribute.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
318
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
319 * If the `detach_process` option is true, detach the current
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
320 process into its own process group, and disassociate from any
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
321 controlling terminal.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
322
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
323 * Set signal handlers as specified by the `signal_map` attribute.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
324
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
325 * If any of the attributes `stdin`, `stdout`, `stderr` are not
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
326 ``None``, bind the system streams `sys.stdin`, `sys.stdout`,
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
327 and/or `sys.stderr` to the files represented by the
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
328 corresponding attributes. Where the attribute has a file
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
329 descriptor, the descriptor is duplicated (instead of re-binding
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
330 the name).
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
331
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
332 * If the `pidfile` attribute is not ``None``, enter its context
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
333 manager.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
334
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
335 * Mark this instance as open (for the purpose of future `open` and
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
336 `close` calls).
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
337
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
338 * Register the `close` method to be called during Python's exit
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
339 processing.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
340
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
341 When the function returns, the running program is a daemon
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
342 process.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
343
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
344 """
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
345 if self.is_open:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
346 return
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
347
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
348 if self.chroot_directory is not None:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
349 change_root_directory(self.chroot_directory)
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
350
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
351 if self.prevent_core:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
352 prevent_core_dump()
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
353
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
354 change_file_creation_mask(self.umask)
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
355 change_working_directory(self.working_directory)
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
356 change_process_owner(self.uid, self.gid)
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
357
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
358 if self.detach_process:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
359 detach_process_context()
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
360
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
361 signal_handler_map = self._make_signal_handler_map()
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
362 set_signal_handlers(signal_handler_map)
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
363
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
364 exclude_fds = self._get_exclude_file_descriptors()
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
365 close_all_open_files(exclude=exclude_fds)
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
366
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
367 redirect_stream(sys.stdin, self.stdin)
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
368 redirect_stream(sys.stdout, self.stdout)
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
369 redirect_stream(sys.stderr, self.stderr)
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
370
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
371 if self.pidfile is not None:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
372 self.pidfile.__enter__()
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
373
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
374 self._is_open = True
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
375
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
376 register_atexit_function(self.close)
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
377
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
378 def __enter__(self):
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
379 """ Context manager entry point. """
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
380 self.open()
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
381 return self
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
382
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
383 def close(self):
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
384 """ Exit the daemon process context.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
385
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
386 :return: ``None``.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
387
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
388 Close the daemon context. This performs the following steps:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
389
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
390 * If this instance's `is_open` property is false, return
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
391 immediately. This makes it safe to call `close` multiple times
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
392 on an instance.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
393
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
394 * If the `pidfile` attribute is not ``None``, exit its context
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
395 manager.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
396
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
397 * Mark this instance as closed (for the purpose of future `open`
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
398 and `close` calls).
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
399
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
400 """
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
401 if not self.is_open:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
402 return
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
403
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
404 if self.pidfile is not None:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
405 # Follow the interface for telling a context manager to exit,
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
406 # <URL:http://docs.python.org/library/stdtypes.html#typecontextmanager>.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
407 self.pidfile.__exit__(None, None, None)
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
408
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
409 self._is_open = False
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
410
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
411 def __exit__(self, exc_type, exc_value, traceback):
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
412 """ Context manager exit point. """
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
413 self.close()
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
414
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
415 def terminate(self, signal_number, stack_frame):
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
416 """ Signal handler for end-process signals.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
417
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
418 :param signal_number: The OS signal number received.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
419 :param stack_frame: The frame object at the point the
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
420 signal was received.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
421 :return: ``None``.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
422
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
423 Signal handler for the ``signal.SIGTERM`` signal. Performs the
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
424 following step:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
425
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
426 * Raise a ``SystemExit`` exception explaining the signal.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
427
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
428 """
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
429 exception = SystemExit(
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
430 "Terminating on signal {signal_number!r}".format(
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
431 signal_number=signal_number))
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
432 raise exception
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
433
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
434 def _get_exclude_file_descriptors(self):
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
435 """ Get the set of file descriptors to exclude closing.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
436
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
437 :return: A set containing the file descriptors for the
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
438 files to be preserved.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
439
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
440 The file descriptors to be preserved are those from the
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
441 items in `files_preserve`, and also each of `stdin`,
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
442 `stdout`, and `stderr`. For each item:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
443
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
444 * If the item is ``None``, it is omitted from the return
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
445 set.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
446
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
447 * If the item's ``fileno()`` method returns a value, that
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
448 value is in the return set.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
449
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
450 * Otherwise, the item is in the return set verbatim.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
451
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
452 """
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
453 files_preserve = self.files_preserve
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
454 if files_preserve is None:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
455 files_preserve = []
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
456 files_preserve.extend(
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
457 item for item in [self.stdin, self.stdout, self.stderr]
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
458 if hasattr(item, 'fileno'))
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
459
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
460 exclude_descriptors = set()
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
461 for item in files_preserve:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
462 if item is None:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
463 continue
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
464 file_descriptor = _get_file_descriptor(item)
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
465 if file_descriptor is not None:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
466 exclude_descriptors.add(file_descriptor)
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
467 else:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
468 exclude_descriptors.add(item)
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
469
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
470 return exclude_descriptors
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
471
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
472 def _make_signal_handler(self, target):
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
473 """ Make the signal handler for a specified target object.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
474
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
475 :param target: A specification of the target for the
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
476 handler; see below.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
477 :return: The value for use by `signal.signal()`.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
478
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
479 If `target` is ``None``, return ``signal.SIG_IGN``. If `target`
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
480 is a text string, return the attribute of this instance named
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
481 by that string. Otherwise, return `target` itself.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
482
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
483 """
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
484 if target is None:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
485 result = signal.SIG_IGN
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
486 elif isinstance(target, unicode):
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
487 name = target
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
488 result = getattr(self, name)
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
489 else:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
490 result = target
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
491
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
492 return result
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
493
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
494 def _make_signal_handler_map(self):
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
495 """ Make the map from signals to handlers for this instance.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
496
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
497 :return: The constructed signal map for this instance.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
498
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
499 Construct a map from signal numbers to handlers for this
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
500 context instance, suitable for passing to
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
501 `set_signal_handlers`.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
502
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
503 """
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
504 signal_handler_map = dict(
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
505 (signal_number, self._make_signal_handler(target))
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
506 for (signal_number, target) in self.signal_map.items())
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
507 return signal_handler_map
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
508
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
509
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
510 def _get_file_descriptor(obj):
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
511 """ Get the file descriptor, if the object has one.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
512
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
513 :param obj: The object expected to be a file-like object.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
514 :return: The file descriptor iff the file supports it; otherwise
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
515 ``None``.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
516
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
517 The object may be a non-file object. It may also be a
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
518 file-like object with no support for a file descriptor. In
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
519 either case, return ``None``.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
520
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
521 """
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
522 file_descriptor = None
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
523 if hasattr(obj, 'fileno'):
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
524 try:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
525 file_descriptor = obj.fileno()
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
526 except ValueError:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
527 # The item doesn't support a file descriptor.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
528 pass
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
529
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
530 return file_descriptor
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
531
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
532
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
533 def change_working_directory(directory):
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
534 """ Change the working directory of this process.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
535
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
536 :param directory: The target directory path.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
537 :return: ``None``.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
538
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
539 """
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
540 try:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
541 os.chdir(directory)
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
542 except Exception as exc:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
543 error = DaemonOSEnvironmentError(
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
544 "Unable to change working directory ({exc})".format(exc=exc))
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
545 raise error
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
546
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
547
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
548 def change_root_directory(directory):
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
549 """ Change the root directory of this process.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
550
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
551 :param directory: The target directory path.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
552 :return: ``None``.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
553
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
554 Set the current working directory, then the process root directory,
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
555 to the specified `directory`. Requires appropriate OS privileges
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
556 for this process.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
557
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
558 """
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
559 try:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
560 os.chdir(directory)
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
561 os.chroot(directory)
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
562 except Exception as exc:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
563 error = DaemonOSEnvironmentError(
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
564 "Unable to change root directory ({exc})".format(exc=exc))
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
565 raise error
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
566
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
567
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
568 def change_file_creation_mask(mask):
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
569 """ Change the file creation mask for this process.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
570
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
571 :param mask: The numeric file creation mask to set.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
572 :return: ``None``.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
573
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
574 """
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
575 try:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
576 os.umask(mask)
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
577 except Exception as exc:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
578 error = DaemonOSEnvironmentError(
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
579 "Unable to change file creation mask ({exc})".format(exc=exc))
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
580 raise error
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
581
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
582
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
583 def change_process_owner(uid, gid):
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
584 """ Change the owning UID and GID of this process.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
585
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
586 :param uid: The target UID for the daemon process.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
587 :param gid: The target GID for the daemon process.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
588 :return: ``None``.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
589
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
590 Set the GID then the UID of the process (in that order, to avoid
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
591 permission errors) to the specified `gid` and `uid` values.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
592 Requires appropriate OS privileges for this process.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
593
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
594 """
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
595 try:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
596 os.setgid(gid)
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
597 os.setuid(uid)
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
598 except Exception as exc:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
599 error = DaemonOSEnvironmentError(
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
600 "Unable to change process owner ({exc})".format(exc=exc))
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
601 raise error
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
602
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
603
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
604 def prevent_core_dump():
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
605 """ Prevent this process from generating a core dump.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
606
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
607 :return: ``None``.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
608
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
609 Set the soft and hard limits for core dump size to zero. On Unix,
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
610 this entirely prevents the process from creating core dump.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
611
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
612 """
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
613 core_resource = resource.RLIMIT_CORE
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
614
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
615 try:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
616 # Ensure the resource limit exists on this platform, by requesting
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
617 # its current value.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
618 core_limit_prev = resource.getrlimit(core_resource)
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
619 except ValueError as exc:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
620 error = DaemonOSEnvironmentError(
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
621 "System does not support RLIMIT_CORE resource limit"
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
622 " ({exc})".format(exc=exc))
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
623 raise error
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
624
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
625 # Set hard and soft limits to zero, i.e. no core dump at all.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
626 core_limit = (0, 0)
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
627 resource.setrlimit(core_resource, core_limit)
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
628
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
629
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
630 def detach_process_context():
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
631 """ Detach the process context from parent and session.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
632
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
633 :return: ``None``.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
634
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
635 Detach from the parent process and session group, allowing the
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
636 parent to exit while this process continues running.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
637
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
638 Reference: “Advanced Programming in the Unix Environment”,
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
639 section 13.3, by W. Richard Stevens, published 1993 by
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
640 Addison-Wesley.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
641
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
642 """
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
643
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
644 def fork_then_exit_parent(error_message):
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
645 """ Fork a child process, then exit the parent process.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
646
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
647 :param error_message: Message for the exception in case of a
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
648 detach failure.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
649 :return: ``None``.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
650 :raise DaemonProcessDetachError: If the fork fails.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
651
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
652 """
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
653 try:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
654 pid = os.fork()
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
655 if pid > 0:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
656 os._exit(0)
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
657 except OSError as exc:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
658 error = DaemonProcessDetachError(
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
659 "{message}: [{exc.errno:d}] {exc.strerror}".format(
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
660 message=error_message, exc=exc))
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
661 raise error
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
662
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
663 fork_then_exit_parent(error_message="Failed first fork")
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
664 os.setsid()
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
665 fork_then_exit_parent(error_message="Failed second fork")
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
666
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
667
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
668 def is_process_started_by_init():
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
669 """ Determine whether the current process is started by `init`.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
670
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
671 :return: ``True`` iff the parent process is `init`; otherwise
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
672 ``False``.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
673
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
674 The `init` process is the one with process ID of 1.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
675
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
676 """
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
677 result = False
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
678
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
679 init_pid = 1
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
680 if os.getppid() == init_pid:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
681 result = True
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
682
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
683 return result
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
684
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
685
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
686 def is_socket(fd):
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
687 """ Determine whether the file descriptor is a socket.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
688
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
689 :param fd: The file descriptor to interrogate.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
690 :return: ``True`` iff the file descriptor is a socket; otherwise
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
691 ``False``.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
692
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
693 Query the socket type of `fd`. If there is no error, the file is a
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
694 socket.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
695
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
696 """
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
697 result = False
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
698
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
699 file_socket = socket.fromfd(fd, socket.AF_INET, socket.SOCK_RAW)
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
700
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
701 try:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
702 socket_type = file_socket.getsockopt(
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
703 socket.SOL_SOCKET, socket.SO_TYPE)
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
704 except socket.error as exc:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
705 exc_errno = exc.args[0]
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
706 if exc_errno == errno.ENOTSOCK:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
707 # Socket operation on non-socket.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
708 pass
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
709 else:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
710 # Some other socket error.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
711 result = True
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
712 else:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
713 # No error getting socket type.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
714 result = True
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
715
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
716 return result
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
717
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
718
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
719 def is_process_started_by_superserver():
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
720 """ Determine whether the current process is started by the superserver.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
721
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
722 :return: ``True`` if this process was started by the internet
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
723 superserver; otherwise ``False``.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
724
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
725 The internet superserver creates a network socket, and
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
726 attaches it to the standard streams of the child process. If
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
727 that is the case for this process, return ``True``, otherwise
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
728 ``False``.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
729
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
730 """
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
731 result = False
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
732
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
733 stdin_fd = sys.__stdin__.fileno()
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
734 if is_socket(stdin_fd):
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
735 result = True
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
736
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
737 return result
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
738
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
739
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
740 def is_detach_process_context_required():
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
741 """ Determine whether detaching the process context is required.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
742
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
743 :return: ``True`` iff the process is already detached; otherwise
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
744 ``False``.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
745
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
746 The process environment is interrogated for the following:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
747
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
748 * Process was started by `init`; or
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
749
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
750 * Process was started by `inetd`.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
751
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
752 If any of the above are true, the process is deemed to be already
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
753 detached.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
754
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
755 """
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
756 result = True
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
757 if is_process_started_by_init() or is_process_started_by_superserver():
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
758 result = False
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
759
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
760 return result
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
761
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
762
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
763 def close_file_descriptor_if_open(fd):
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
764 """ Close a file descriptor if already open.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
765
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
766 :param fd: The file descriptor to close.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
767 :return: ``None``.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
768
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
769 Close the file descriptor `fd`, suppressing an error in the
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
770 case the file was not open.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
771
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
772 """
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
773 try:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
774 os.close(fd)
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
775 except EnvironmentError as exc:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
776 if exc.errno == errno.EBADF:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
777 # File descriptor was not open.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
778 pass
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
779 else:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
780 error = DaemonOSEnvironmentError(
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
781 "Failed to close file descriptor {fd:d} ({exc})".format(
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
782 fd=fd, exc=exc))
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
783 raise error
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
784
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
785
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
786 MAXFD = 2048
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
787
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
788 def get_maximum_file_descriptors():
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
789 """ Get the maximum number of open file descriptors for this process.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
790
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
791 :return: The number (integer) to use as the maximum number of open
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
792 files for this process.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
793
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
794 The maximum is the process hard resource limit of maximum number of
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
795 open file descriptors. If the limit is “infinity”, a default value
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
796 of ``MAXFD`` is returned.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
797
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
798 """
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
799 limits = resource.getrlimit(resource.RLIMIT_NOFILE)
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
800 result = limits[1]
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
801 if result == resource.RLIM_INFINITY:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
802 result = MAXFD
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
803 return result
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
804
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
805
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
806 def close_all_open_files(exclude=set()):
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
807 """ Close all open file descriptors.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
808
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
809 :param exclude: Collection of file descriptors to skip when closing
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
810 files.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
811 :return: ``None``.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
812
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
813 Closes every file descriptor (if open) of this process. If
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
814 specified, `exclude` is a set of file descriptors to *not*
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
815 close.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
816
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
817 """
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
818 maxfd = get_maximum_file_descriptors()
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
819 for fd in reversed(range(maxfd)):
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
820 if fd not in exclude:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
821 close_file_descriptor_if_open(fd)
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
822
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
823
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
824 def redirect_stream(system_stream, target_stream):
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
825 """ Redirect a system stream to a specified file.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
826
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
827 :param standard_stream: A file object representing a standard I/O
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
828 stream.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
829 :param target_stream: The target file object for the redirected
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
830 stream, or ``None`` to specify the null device.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
831 :return: ``None``.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
832
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
833 `system_stream` is a standard system stream such as
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
834 ``sys.stdout``. `target_stream` is an open file object that
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
835 should replace the corresponding system stream object.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
836
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
837 If `target_stream` is ``None``, defaults to opening the
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
838 operating system's null device and using its file descriptor.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
839
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
840 """
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
841 if target_stream is None:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
842 target_fd = os.open(os.devnull, os.O_RDWR)
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
843 else:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
844 target_fd = target_stream.fileno()
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
845 os.dup2(target_fd, system_stream.fileno())
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
846
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
847
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
848 def make_default_signal_map():
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
849 """ Make the default signal map for this system.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
850
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
851 :return: A mapping from signal number to handler object.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
852
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
853 The signals available differ by system. The map will not contain
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
854 any signals not defined on the running system.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
855
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
856 """
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
857 name_map = {
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
858 'SIGTSTP': None,
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
859 'SIGTTIN': None,
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
860 'SIGTTOU': None,
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
861 'SIGTERM': 'terminate',
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
862 }
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
863 signal_map = dict(
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
864 (getattr(signal, name), target)
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
865 for (name, target) in name_map.items()
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
866 if hasattr(signal, name))
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
867
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
868 return signal_map
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
869
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
870
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
871 def set_signal_handlers(signal_handler_map):
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
872 """ Set the signal handlers as specified.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
873
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
874 :param signal_handler_map: A map from signal number to handler
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
875 object.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
876 :return: ``None``.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
877
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
878 See the `signal` module for details on signal numbers and signal
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
879 handlers.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
880
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
881 """
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
882 for (signal_number, handler) in signal_handler_map.items():
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
883 signal.signal(signal_number, handler)
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
884
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
885
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
886 def register_atexit_function(func):
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
887 """ Register a function for processing at program exit.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
888
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
889 :param func: A callable function expecting no arguments.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
890 :return: ``None``.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
891
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
892 The function `func` is registered for a call with no arguments
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
893 at program exit.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
894
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
895 """
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
896 atexit.register(func)
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
897
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
898
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
899 def _chain_exception_from_existing_exception_context(exc, as_cause=False):
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
900 """ Decorate the specified exception with the existing exception context.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
901
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
902 :param exc: The exception instance to decorate.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
903 :param as_cause: If true, the existing context is declared to be
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
904 the cause of the exception.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
905 :return: ``None``.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
906
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
907 :PEP:`344` describes syntax and attributes (`__traceback__`,
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
908 `__context__`, `__cause__`) for use in exception chaining.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
909
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
910 Python 2 does not have that syntax, so this function decorates
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
911 the exception with values from the current exception context.
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
912
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
913 """
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
914 (existing_exc_type, existing_exc, existing_traceback) = sys.exc_info()
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
915 if as_cause:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
916 exc.__cause__ = existing_exc
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
917 else:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
918 exc.__context__ = existing_exc
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
919 exc.__traceback__ = existing_traceback
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
920
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
921
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
922 # Local variables:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
923 # coding: utf-8
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
924 # mode: python
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
925 # End:
7ceb967147c3 start xena with no gui
jingchunzhu <jingchunzhu@gmail.com>
parents:
diff changeset
926 # vim: fileencoding=utf-8 filetype=python :