root / lib / utils / wrapper.py @ 653bc0f1
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") |