Statistics
| Branch: | Tag: | Revision:

root / lib / utils / wrapper.py @ 81f7ea25

History | View | Annotate | Download (5 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 7831fc5f Michael Hanselmann
  @param duration: the sleep duration
41 7831fc5f Michael Hanselmann
  @rtype: boolean
42 7831fc5f Michael Hanselmann
  @return: False for negative value, True otherwise
43 7831fc5f Michael Hanselmann

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

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

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

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

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

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

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

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

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

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

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

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

169 7831fc5f Michael Hanselmann
  """
170 7831fc5f Michael Hanselmann
  (fd, path) = tempfile.mkstemp(*args, **kwargs)
171 7831fc5f Michael Hanselmann
  CloseFdNoError(fd)
172 7831fc5f Michael Hanselmann
  return path
173 44c9b4fe Michael Hanselmann
174 44c9b4fe Michael Hanselmann
175 380bb53a Michael Hanselmann
def ResetTempfileModule(_time=time.time):
176 44c9b4fe Michael Hanselmann
  """Resets the random name generator of the tempfile module.
177 44c9b4fe Michael Hanselmann

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

184 44c9b4fe Michael Hanselmann
  """
185 b459a848 Andrea Spadaccini
  # pylint: disable=W0212
186 035b33e2 Iustin Pop
  if ((sys.hexversion >= 0x020703F0 and sys.hexversion < 0x03000000) or
187 81f7ea25 Iustin Pop
      sys.hexversion >= 0x030203F0):
188 035b33e2 Iustin Pop
    # Python 2.7 automatically resets the RNG on pid changes (i.e. forking)
189 035b33e2 Iustin Pop
    return
190 035b33e2 Iustin Pop
191 380bb53a Michael Hanselmann
  try:
192 380bb53a Michael Hanselmann
    lock = tempfile._once_lock
193 380bb53a Michael Hanselmann
    lock.acquire()
194 44c9b4fe Michael Hanselmann
    try:
195 380bb53a Michael Hanselmann
      # Re-seed random name generator
196 380bb53a Michael Hanselmann
      if tempfile._name_sequence:
197 380bb53a Michael Hanselmann
        tempfile._name_sequence.rng.seed(hash(_time()) ^ os.getpid())
198 44c9b4fe Michael Hanselmann
    finally:
199 380bb53a Michael Hanselmann
      lock.release()
200 380bb53a Michael Hanselmann
  except AttributeError:
201 44c9b4fe Michael Hanselmann
    logging.critical("The tempfile module misses at least one of the"
202 44c9b4fe Michael Hanselmann
                     " '_once_lock' and '_name_sequence' attributes")