Statistics
| Branch: | Tag: | Revision:

root / lib / utils / wrapper.py @ 1cc324f0

History | View | Annotate | Download (5.3 kB)

1 7831fc5f Michael Hanselmann
#
2 7831fc5f Michael Hanselmann
#
3 7831fc5f Michael Hanselmann
4 035b33e2 Iustin Pop
# Copyright (C) 2006, 2007, 2010, 2011, 2012 Google Inc.
5 7831fc5f Michael Hanselmann
#
6 7831fc5f Michael Hanselmann
# This program is free software; you can redistribute it and/or modify
7 7831fc5f Michael Hanselmann
# it under the terms of the GNU General Public License as published by
8 7831fc5f Michael Hanselmann
# the Free Software Foundation; either version 2 of the License, or
9 7831fc5f Michael Hanselmann
# (at your option) any later version.
10 7831fc5f Michael Hanselmann
#
11 7831fc5f Michael Hanselmann
# This program is distributed in the hope that it will be useful, but
12 7831fc5f Michael Hanselmann
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 7831fc5f Michael Hanselmann
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 7831fc5f Michael Hanselmann
# General Public License for more details.
15 7831fc5f Michael Hanselmann
#
16 7831fc5f Michael Hanselmann
# You should have received a copy of the GNU General Public License
17 7831fc5f Michael Hanselmann
# along with this program; if not, write to the Free Software
18 7831fc5f Michael Hanselmann
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 7831fc5f Michael Hanselmann
# 02110-1301, USA.
20 7831fc5f Michael Hanselmann
21 7831fc5f Michael Hanselmann
"""Utility functions wrapping other functions.
22 7831fc5f Michael Hanselmann

23 7831fc5f Michael Hanselmann
"""
24 7831fc5f Michael Hanselmann
25 035b33e2 Iustin Pop
import sys
26 7831fc5f Michael Hanselmann
import time
27 7831fc5f Michael Hanselmann
import socket
28 7831fc5f Michael Hanselmann
import errno
29 7831fc5f Michael Hanselmann
import tempfile
30 7831fc5f Michael Hanselmann
import fcntl
31 7831fc5f Michael Hanselmann
import os
32 7831fc5f Michael Hanselmann
import select
33 44c9b4fe Michael Hanselmann
import logging
34 7831fc5f Michael Hanselmann
35 7831fc5f Michael Hanselmann
36 7831fc5f Michael Hanselmann
def TestDelay(duration):
37 7831fc5f Michael Hanselmann
  """Sleep for a fixed amount of time.
38 7831fc5f Michael Hanselmann

39 7831fc5f Michael Hanselmann
  @type duration: float
40 aeb6ba44 Dato Simó
  @param duration: the sleep duration, in seconds
41 aeb6ba44 Dato Simó
  @rtype: (boolean, str)
42 aeb6ba44 Dato Simó
  @return: False for negative value, and an accompanying error message;
43 aeb6ba44 Dato Simó
      True otherwise (and msg is None)
44 7831fc5f Michael Hanselmann

45 7831fc5f Michael Hanselmann
  """
46 7831fc5f Michael Hanselmann
  if duration < 0:
47 7831fc5f Michael Hanselmann
    return False, "Invalid sleep duration"
48 7831fc5f Michael Hanselmann
  time.sleep(duration)
49 7831fc5f Michael Hanselmann
  return True, None
50 7831fc5f Michael Hanselmann
51 7831fc5f Michael Hanselmann
52 7831fc5f Michael Hanselmann
def CloseFdNoError(fd, retries=5):
53 7831fc5f Michael Hanselmann
  """Close a file descriptor ignoring errors.
54 7831fc5f Michael Hanselmann

55 7831fc5f Michael Hanselmann
  @type fd: int
56 7831fc5f Michael Hanselmann
  @param fd: the file descriptor
57 7831fc5f Michael Hanselmann
  @type retries: int
58 7831fc5f Michael Hanselmann
  @param retries: how many retries to make, in case we get any
59 7831fc5f Michael Hanselmann
      other error than EBADF
60 7831fc5f Michael Hanselmann

61 7831fc5f Michael Hanselmann
  """
62 7831fc5f Michael Hanselmann
  try:
63 7831fc5f Michael Hanselmann
    os.close(fd)
64 7831fc5f Michael Hanselmann
  except OSError, err:
65 7831fc5f Michael Hanselmann
    if err.errno != errno.EBADF:
66 7831fc5f Michael Hanselmann
      if retries > 0:
67 7831fc5f Michael Hanselmann
        CloseFdNoError(fd, retries - 1)
68 7831fc5f Michael Hanselmann
    # else either it's closed already or we're out of retries, so we
69 7831fc5f Michael Hanselmann
    # ignore this and go on
70 7831fc5f Michael Hanselmann
71 7831fc5f Michael Hanselmann
72 7831fc5f Michael Hanselmann
def SetCloseOnExecFlag(fd, enable):
73 7831fc5f Michael Hanselmann
  """Sets or unsets the close-on-exec flag on a file descriptor.
74 7831fc5f Michael Hanselmann

75 7831fc5f Michael Hanselmann
  @type fd: int
76 7831fc5f Michael Hanselmann
  @param fd: File descriptor
77 7831fc5f Michael Hanselmann
  @type enable: bool
78 7831fc5f Michael Hanselmann
  @param enable: Whether to set or unset it.
79 7831fc5f Michael Hanselmann

80 7831fc5f Michael Hanselmann
  """
81 7831fc5f Michael Hanselmann
  flags = fcntl.fcntl(fd, fcntl.F_GETFD)
82 7831fc5f Michael Hanselmann
83 7831fc5f Michael Hanselmann
  if enable:
84 7831fc5f Michael Hanselmann
    flags |= fcntl.FD_CLOEXEC
85 7831fc5f Michael Hanselmann
  else:
86 7831fc5f Michael Hanselmann
    flags &= ~fcntl.FD_CLOEXEC
87 7831fc5f Michael Hanselmann
88 7831fc5f Michael Hanselmann
  fcntl.fcntl(fd, fcntl.F_SETFD, flags)
89 7831fc5f Michael Hanselmann
90 7831fc5f Michael Hanselmann
91 7831fc5f Michael Hanselmann
def SetNonblockFlag(fd, enable):
92 7831fc5f Michael Hanselmann
  """Sets or unsets the O_NONBLOCK flag on on a file descriptor.
93 7831fc5f Michael Hanselmann

94 7831fc5f Michael Hanselmann
  @type fd: int
95 7831fc5f Michael Hanselmann
  @param fd: File descriptor
96 7831fc5f Michael Hanselmann
  @type enable: bool
97 7831fc5f Michael Hanselmann
  @param enable: Whether to set or unset it
98 7831fc5f Michael Hanselmann

99 7831fc5f Michael Hanselmann
  """
100 7831fc5f Michael Hanselmann
  flags = fcntl.fcntl(fd, fcntl.F_GETFL)
101 7831fc5f Michael Hanselmann
102 7831fc5f Michael Hanselmann
  if enable:
103 7831fc5f Michael Hanselmann
    flags |= os.O_NONBLOCK
104 7831fc5f Michael Hanselmann
  else:
105 7831fc5f Michael Hanselmann
    flags &= ~os.O_NONBLOCK
106 7831fc5f Michael Hanselmann
107 7831fc5f Michael Hanselmann
  fcntl.fcntl(fd, fcntl.F_SETFL, flags)
108 7831fc5f Michael Hanselmann
109 7831fc5f Michael Hanselmann
110 7831fc5f Michael Hanselmann
def RetryOnSignal(fn, *args, **kwargs):
111 7831fc5f Michael Hanselmann
  """Calls a function again if it failed due to EINTR.
112 7831fc5f Michael Hanselmann

113 7831fc5f Michael Hanselmann
  """
114 7831fc5f Michael Hanselmann
  while True:
115 7831fc5f Michael Hanselmann
    try:
116 7831fc5f Michael Hanselmann
      return fn(*args, **kwargs)
117 7831fc5f Michael Hanselmann
    except EnvironmentError, err:
118 7831fc5f Michael Hanselmann
      if err.errno != errno.EINTR:
119 7831fc5f Michael Hanselmann
        raise
120 7831fc5f Michael Hanselmann
    except (socket.error, select.error), err:
121 7831fc5f Michael Hanselmann
      # In python 2.6 and above select.error is an IOError, so it's handled
122 7831fc5f Michael Hanselmann
      # above, in 2.5 and below it's not, and it's handled here.
123 7831fc5f Michael Hanselmann
      if not (err.args and err.args[0] == errno.EINTR):
124 7831fc5f Michael Hanselmann
        raise
125 7831fc5f Michael Hanselmann
126 7831fc5f Michael Hanselmann
127 7831fc5f Michael Hanselmann
def IgnoreProcessNotFound(fn, *args, **kwargs):
128 7831fc5f Michael Hanselmann
  """Ignores ESRCH when calling a process-related function.
129 7831fc5f Michael Hanselmann

130 7831fc5f Michael Hanselmann
  ESRCH is raised when a process is not found.
131 7831fc5f Michael Hanselmann

132 7831fc5f Michael Hanselmann
  @rtype: bool
133 7831fc5f Michael Hanselmann
  @return: Whether process was found
134 7831fc5f Michael Hanselmann

135 7831fc5f Michael Hanselmann
  """
136 7831fc5f Michael Hanselmann
  try:
137 7831fc5f Michael Hanselmann
    fn(*args, **kwargs)
138 7831fc5f Michael Hanselmann
  except EnvironmentError, err:
139 7831fc5f Michael Hanselmann
    # Ignore ESRCH
140 7831fc5f Michael Hanselmann
    if err.errno == errno.ESRCH:
141 7831fc5f Michael Hanselmann
      return False
142 7831fc5f Michael Hanselmann
    raise
143 7831fc5f Michael Hanselmann
144 7831fc5f Michael Hanselmann
  return True
145 7831fc5f Michael Hanselmann
146 7831fc5f Michael Hanselmann
147 7831fc5f Michael Hanselmann
def IgnoreSignals(fn, *args, **kwargs):
148 7831fc5f Michael Hanselmann
  """Tries to call a function ignoring failures due to EINTR.
149 7831fc5f Michael Hanselmann

150 7831fc5f Michael Hanselmann
  """
151 7831fc5f Michael Hanselmann
  try:
152 7831fc5f Michael Hanselmann
    return fn(*args, **kwargs)
153 7831fc5f Michael Hanselmann
  except EnvironmentError, err:
154 7831fc5f Michael Hanselmann
    if err.errno == errno.EINTR:
155 7831fc5f Michael Hanselmann
      return None
156 7831fc5f Michael Hanselmann
    else:
157 7831fc5f Michael Hanselmann
      raise
158 7831fc5f Michael Hanselmann
  except (select.error, socket.error), err:
159 7831fc5f Michael Hanselmann
    # In python 2.6 and above select.error is an IOError, so it's handled
160 7831fc5f Michael Hanselmann
    # above, in 2.5 and below it's not, and it's handled here.
161 7831fc5f Michael Hanselmann
    if err.args and err.args[0] == errno.EINTR:
162 7831fc5f Michael Hanselmann
      return None
163 7831fc5f Michael Hanselmann
    else:
164 7831fc5f Michael Hanselmann
      raise
165 7831fc5f Michael Hanselmann
166 7831fc5f Michael Hanselmann
167 7831fc5f Michael Hanselmann
def GetClosedTempfile(*args, **kwargs):
168 7831fc5f Michael Hanselmann
  """Creates a temporary file and returns its path.
169 7831fc5f Michael Hanselmann

170 7831fc5f Michael Hanselmann
  """
171 7831fc5f Michael Hanselmann
  (fd, path) = tempfile.mkstemp(*args, **kwargs)
172 7831fc5f Michael Hanselmann
  CloseFdNoError(fd)
173 7831fc5f Michael Hanselmann
  return path
174 44c9b4fe Michael Hanselmann
175 44c9b4fe Michael Hanselmann
176 10b86782 Michael Hanselmann
def IsExecutable(filename):
177 10b86782 Michael Hanselmann
  """Checks whether a file exists and is executable.
178 10b86782 Michael Hanselmann

179 10b86782 Michael Hanselmann
  @type filename: string
180 10b86782 Michael Hanselmann
  @param filename: Filename
181 10b86782 Michael Hanselmann
  @rtype: bool
182 10b86782 Michael Hanselmann

183 10b86782 Michael Hanselmann
  """
184 10b86782 Michael Hanselmann
  return os.path.isfile(filename) and os.access(filename, os.X_OK)
185 10b86782 Michael Hanselmann
186 10b86782 Michael Hanselmann
187 380bb53a Michael Hanselmann
def ResetTempfileModule(_time=time.time):
188 44c9b4fe Michael Hanselmann
  """Resets the random name generator of the tempfile module.
189 44c9b4fe Michael Hanselmann

190 44c9b4fe Michael Hanselmann
  This function should be called after C{os.fork} in the child process to
191 44c9b4fe Michael Hanselmann
  ensure it creates a newly seeded random generator. Otherwise it would
192 44c9b4fe Michael Hanselmann
  generate the same random parts as the parent process. If several processes
193 44c9b4fe Michael Hanselmann
  race for the creation of a temporary file, this could lead to one not getting
194 44c9b4fe Michael Hanselmann
  a temporary name.
195 44c9b4fe Michael Hanselmann

196 44c9b4fe Michael Hanselmann
  """
197 b459a848 Andrea Spadaccini
  # pylint: disable=W0212
198 035b33e2 Iustin Pop
  if ((sys.hexversion >= 0x020703F0 and sys.hexversion < 0x03000000) or
199 81f7ea25 Iustin Pop
      sys.hexversion >= 0x030203F0):
200 035b33e2 Iustin Pop
    # Python 2.7 automatically resets the RNG on pid changes (i.e. forking)
201 035b33e2 Iustin Pop
    return
202 035b33e2 Iustin Pop
203 380bb53a Michael Hanselmann
  try:
204 380bb53a Michael Hanselmann
    lock = tempfile._once_lock
205 380bb53a Michael Hanselmann
    lock.acquire()
206 44c9b4fe Michael Hanselmann
    try:
207 380bb53a Michael Hanselmann
      # Re-seed random name generator
208 380bb53a Michael Hanselmann
      if tempfile._name_sequence:
209 380bb53a Michael Hanselmann
        tempfile._name_sequence.rng.seed(hash(_time()) ^ os.getpid())
210 44c9b4fe Michael Hanselmann
    finally:
211 380bb53a Michael Hanselmann
      lock.release()
212 380bb53a Michael Hanselmann
  except AttributeError:
213 44c9b4fe Michael Hanselmann
    logging.critical("The tempfile module misses at least one of the"
214 44c9b4fe Michael Hanselmann
                     " '_once_lock' and '_name_sequence' attributes")