|
@@ -43,7 +43,8 @@ __all__ = ['EX_OK', 'EX_FAILURE', 'EX_UNAVAILABLE', 'EX_USAGE', 'SYSTEM',
|
|
|
'close_open_fds', 'DaemonContext', 'detached', 'parse_uid',
|
|
|
'parse_gid', 'setgroups', 'initgroups', 'setgid', 'setuid',
|
|
|
'maybe_drop_privileges', 'signals', 'set_process_title',
|
|
|
- 'set_mp_process_title', 'get_errno_name', 'ignore_errno']
|
|
|
+ 'set_mp_process_title', 'get_errno_name', 'ignore_errno',
|
|
|
+ 'fd_by_path']
|
|
|
|
|
|
# exitcodes
|
|
|
EX_OK = getattr(os, 'EX_OK', 0)
|
|
@@ -264,6 +265,43 @@ def _create_pidlock(pidfile):
|
|
|
pidlock.acquire()
|
|
|
return pidlock
|
|
|
|
|
|
+def fd_by_path(paths):
|
|
|
+ """
|
|
|
+ Return a list of fds.
|
|
|
+
|
|
|
+ This method returns list of fds corresponding to
|
|
|
+ file paths passed in paths variable.
|
|
|
+
|
|
|
+ :keyword paths: List of file paths go get fd for.
|
|
|
+
|
|
|
+ :returns: :list:.
|
|
|
+
|
|
|
+ **Example**:
|
|
|
+
|
|
|
+ .. code-block:: python
|
|
|
+
|
|
|
+ keep = fd_by_path(['/dev/urandom',
|
|
|
+ '/my/precious/'])
|
|
|
+ """
|
|
|
+ stats = set()
|
|
|
+ for path in paths:
|
|
|
+ try:
|
|
|
+ fd = os.open(path, os.O_RDONLY)
|
|
|
+ except OSError:
|
|
|
+ continue
|
|
|
+ try:
|
|
|
+ stats.add(os.fstat(fd)[1:3])
|
|
|
+ finally:
|
|
|
+ os.close(fd)
|
|
|
+
|
|
|
+ def fd_in_stats(fd):
|
|
|
+ try:
|
|
|
+ return os.fstat(fd)[1:3] in stats
|
|
|
+ except OSError:
|
|
|
+ return False
|
|
|
+
|
|
|
+ return [fd for fd in range(get_fdmax(2048)) if fd_in_stats(fd)]
|
|
|
+
|
|
|
|
|
|
if hasattr(os, 'closerange'):
|
|
|
|
|
@@ -321,7 +359,10 @@ class DaemonContext(object):
|
|
|
self.after_chdir()
|
|
|
|
|
|
if not self.fake:
|
|
|
- close_open_fds(self.stdfds)
|
|
|
+ # We need to keep /dev/urandom from closing because
|
|
|
+ # shelve needs it, and Beat needs shelve to start.
|
|
|
+ keep = list(self.stdfds) + fd_by_path(['/dev/urandom'])
|
|
|
+ close_open_fds(keep)
|
|
|
for fd in self.stdfds:
|
|
|
self.redirect_to_null(maybe_fileno(fd))
|
|
|
|