This file is indexed.

/usr/lib/python2.7/dist-packages/application/process.py is in python-application 1.4.1-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
# Copyright (C) 2006-2012 Dan Pascu. See LICENSE for details.
#

"""UNIX process and signal management"""

__all__ = ['Process', 'ProcessError', 'Signals', 'process']

import sys
import os
import errno
import signal
import atexit

from application import log
from application.python.types import Singleton


class ProcessError(Exception): pass


class Process(object):
    """Control how the current process runs and interacts with the operating system"""

    __metaclass__ = Singleton

    def __init__(self):
        self._daemon = False
        self._pidfile = None
        self.signals = Signals()
        self._runtime_directory = '/var/run'
        self._system_config_directory = '/etc'
        self._local_config_directory = os.path.realpath(os.path.dirname(sys.argv[0]))

    def _get_local_config_directory(self):
        return self._local_config_directory

    def _set_local_config_directory(self, path):
        self._local_config_directory = os.path.realpath(path)

    local_config_directory = property(_get_local_config_directory, _set_local_config_directory)

    def _get_system_config_directory(self):
        return self._system_config_directory

    def _set_system_config_directory(self, path):
        self._system_config_directory = os.path.realpath(path)

    system_config_directory = property(_get_system_config_directory, _set_system_config_directory)

    def _get_runtime_directory(self):
        return self._runtime_directory

    def _set_runtime_directory(self, path):
        path = os.path.realpath(path)
        if not os.path.isdir(path):
            try:
                os.makedirs(path)
            except OSError, e:
                raise ProcessError("cannot set runtime directory to %s: %s" % (path, e.args[1]))
        if not os.access(path, os.X_OK | os.W_OK):
            raise ProcessError("runtime directory %s is not writable" % path)
        self._runtime_directory = path

    runtime_directory = property(_get_runtime_directory, _set_runtime_directory)

    def _check_if_running(self):
        """Check if the process is already running"""
        pidfile = self._pidfile
        if pidfile is None or not os.path.isfile(pidfile):
            return
        try:
            pf = open(pidfile, 'rb')
        except IOError, why:
            raise ProcessError("unable to open pidfile %s: %s" % (pidfile, str(why)))
        else:
            try:
                try:
                    pid = int(pf.readline().strip())
                except IOError, why:
                    raise ProcessError("unable to read pidfile %s: %s" % (pidfile, str(why)))
                except ValueError:
                    pass
                else:
                    ## Check if the process identified by pid is running
                    ## Send the process a signal of zero (0)
                    try:
                        os.kill(pid, 0)
                    except OSError, why:
                        if why[0] in (errno.EPERM, errno.EACCES):
                            raise ProcessError("already running with pid %d" % pid)
                    else:
                        raise ProcessError("already running with pid %d" % pid)
            finally:
                pf.close()

    def _do_fork(self):
        """Perform the Unix double fork"""
        ## First fork.
        ## This will return control to the command line/shell that invoked us and
        ## will guarantee that the forked child will not be a process group leader
        ## (which is required for setsid() below to succeed).
        try:
            pid = os.fork()
            if pid > 0:
                sys.exit(0) ## exit parent
                #os._exit(0)
        except OSError, e:
            raise ProcessError("fork #1 failed: %d: %s" % (e.errno, e.strerror))
        
        ## Decouple from the controling terminal.
        ## Calling setsid() we become a process group and session group leader.
        ## Since a controlling terminal is associated with a session, and this
        ## new session has not yet acquired a controlling terminal our process
        ## now has no controlling terminal, which is a Good Thing for daemons.
        os.setsid()
        
        ## Second fork
        ## This will allow the parent (the session group leader obtained above)
        ## to exit. This means that the child, as a non-session group leader,
        ## can never regain a controlling terminal.
        try:
            pid = os.fork()
            if pid > 0:
                sys.exit(0) ## exit 1st child too
                #os._exit(0)
        except OSError, e:
            raise ProcessError("fork #2 failed: %d: %s" % (e.errno, e.strerror))
        
        ## Setup our environment.
        ## Change working directory to / so we do not keep any directory in use
        ## preventing them from being unmounted. Also set file creation mask.
        os.chdir("/")
        os.umask(022)

    def _make_pidfile(self):
        """Create the pidfile if defined"""
        if not self._pidfile:
            return
        try:
            pf = open(self._pidfile, "wb")
            try:
                pf.write("%s\n" % os.getpid())
            finally:
                pf.close()
        except IOError, e:
            raise ProcessError("unable to write pidfile %s: %s" % (self._pidfile, str(e)))

    def _redirect_stdio(self):
        """Redirect stdin, stdout and stderr to /dev/null"""
        sys.stdout.flush()
        sys.stderr.flush()
        null = os.open('/dev/null', os.O_RDWR)
        os.dup2(null, sys.stdin.fileno())
        os.dup2(null, sys.stdout.fileno())
        os.dup2(null, sys.stderr.fileno())
        os.close(null)

    def _setup_signal_handlers(self):
        """Setup the signal handlers for daemon mode"""
        signals = self.signals
        ## Ignore Terminal I/O Signals
        if hasattr(signal, 'SIGTTOU'):
            signals.ignore(signal.SIGTTOU)
        if hasattr(signal, 'SIGTTIN'):
            signals.ignore(signal.SIGTTIN)
        if hasattr(signal, 'SIGTSTP'):
            signals.ignore(signal.SIGTSTP)
        ## Ignore USR signals
        if hasattr(signal, 'SIGUSR1'):
            signals.ignore(signal.SIGUSR1)
        if hasattr(signal, 'SIGUSR2'):
            signals.ignore(signal.SIGUSR2)

    def __on_exit(self):
        if self._pidfile:
            try:
                os.unlink(self._pidfile)
            except OSError, why:
                log.warn("unable to delete pidfile %s: %s" % (self._pidfile, str(why)))

    def daemonize(self, pidfile=None):
        """Detach from terminal and run in the background"""
        if self._daemon:
            raise ProcessError('already in daemon mode')
        self._daemon = True
        if pidfile:
            self._pidfile = self.runtime_file(pidfile)
        self._check_if_running()
        self._do_fork()
        self._make_pidfile()
        self._redirect_stdio()
        self._setup_signal_handlers()
        atexit.register(self.__on_exit)

    def get_config_directories(self):
        """Return a tuple containing the system and local config directories."""
        return (self._system_config_directory, self._local_config_directory)

    def config_file(self, name):
        """Return a config file name. Lookup order: name if absolute, local_dir/name, system_dir/name, None if none found"""
        path = os.path.realpath(os.path.join(self._local_config_directory, name))
        if os.path.isfile(path) and os.access(path, os.R_OK):
            return path
        path = os.path.realpath(os.path.join(self._system_config_directory, name))
        if os.path.isfile(path) and os.access(path, os.R_OK):
            return path
        return None

    def runtime_file(self, name):
        """Return a runtime file name (prepends runtime_directory if defined and name is not absolute, else name)."""
        if name is None:
            return None
        if self.runtime_directory is not None:
            return os.path.realpath(os.path.join(self.runtime_directory, name))
        else:
            return os.path.realpath(name)


class Signals(object):
    """Interface to the system signals"""

    __metaclass__ = Singleton
    
    def __init__(self):
        self._handlers = {}
        if not hasattr(signal, '_original_signal'):
            signal._original_signal = signal.signal

    def __dispatcher(self, signum, frame):
        for handler in self._handlers.get(signum, []):
            handler(signum, frame)

    def add_handler(self, signum, sighandler):
        """Add handler to handler list for signal"""
        if not callable(sighandler):
            raise RuntimeError("signal handler needs to be a callable")
        self._handlers.setdefault(signum, set()).add(sighandler)
        if signal.getsignal(signum) != self.__dispatcher:
            signal._original_signal(signum, self.__dispatcher)

    def ignore(self, signum):
        """Ignore signal"""
        signal._original_signal(signum, signal.SIG_IGN)
        try:
            del self._handlers[signum]
        except KeyError:
            pass

    def default_handler(self, signum):
        """Use default handler for signal"""
        signal._original_signal(signum, signal.SIG_DFL)
        try:
            del self._handlers[signum]
        except KeyError:
            pass

    def steal_handlers(self, enable):
        """Replace signal() from the signal module with add_handler()"""
        if enable:
            signal.signal = self.add_handler
        else:
            signal.signal = signal._original_signal


process = Process()