comparison unix.py @ 128:42c8f5c152a5

Fixed EINTR fatally breaking poll/wait on Python 2.6- (for real this time)
author Oleg Oshmyan <chortos@inbox.lv>
date Mon, 16 May 2011 21:31:43 +0100
parents f5b8a0c0e3cb
children 580f0f4687c3
comparison
equal deleted inserted replaced
127:f5b8a0c0e3cb 128:42c8f5c152a5
20 from signal import SIGTERM, SIGKILL 20 from signal import SIGTERM, SIGKILL
21 except ImportError: 21 except ImportError:
22 SIGTERM = 15 22 SIGTERM = 15
23 SIGKILL = 9 23 SIGKILL = 9
24 24
25 __all__ = 'call', 'kill', 'terminate', 'pause', 'clock' 25 __all__ = 'call', 'kill', 'terminate', 'wait', 'pause', 'clock'
26 26
27 27
28 if not sys.stdin.isatty(): 28 if not sys.stdin.isatty():
29 pause = lambda: sys.stdin.read(1) 29 pause = lambda: sys.stdin.read(1)
30 catch_escape = False 30 catch_escape = False
184 if sys.exc_info()[1].args[0] != EINTR: 184 if sys.exc_info()[1].args[0] != EINTR:
185 raise 185 raise
186 if case.process.poll() is None: 186 if case.process.poll() is None:
187 raise testcases.WallTimeLimitExceeded 187 raise testcases.WallTimeLimitExceeded
188 else: 188 else:
189 case.process.wait() 189 wait(case.process)
190 else: 190 else:
191 if not case.maxwalltime: 191 if not case.maxwalltime:
192 try: 192 try:
193 while case.process.poll() is None: 193 while case.process.poll() is None:
194 s = select((sys.stdin, sigchld_pipe_read), (), ()) 194 s = select((sys.stdin, sigchld_pipe_read), (), ())
195 if (s[0] == [sys.stdin] and 195 if (s[0] == [sys.stdin] and
196 sys.stdin.read(1) == '\33'): 196 sys.stdin.read(1) == '\33'):
197 raise testcases.CanceledByUser 197 raise testcases.CanceledByUser
198 except (SelectError, IOError): 198 except (SelectError, IOError, OSError):
199 if sys.exc_info()[1].args[0] != EINTR: 199 if sys.exc_info()[1].args[0] != EINTR:
200 raise 200 raise
201 else: 201 else:
202 case.process.poll() 202 case.process.poll()
203 else: 203 else:
211 if (s[0] == [sys.stdin] and 211 if (s[0] == [sys.stdin] and
212 sys.stdin.read(1) == '\33'): 212 sys.stdin.read(1) == '\33'):
213 raise testcases.CanceledByUser 213 raise testcases.CanceledByUser
214 else: 214 else:
215 raise testcases.WallTimeLimitExceeded 215 raise testcases.WallTimeLimitExceeded
216 except (SelectError, IOError): 216 except (SelectError, IOError, OSError):
217 if sys.exc_info()[1].args[0] != EINTR: 217 if sys.exc_info()[1].args[0] != EINTR:
218 raise 218 raise
219 else: 219 else:
220 case.process.poll() 220 case.process.poll()
221 finally: 221 finally:
257 # To do this, we not only require os.wait4 to be present but also 257 # To do this, we not only require os.wait4 to be present but also
258 # assume things about the implementation of subprocess.Popen. 258 # assume things about the implementation of subprocess.Popen.
259 try: 259 try:
260 def waitpid_emu(pid, options, _wait4=os.wait4): 260 def waitpid_emu(pid, options, _wait4=os.wait4):
261 global last_rusage 261 global last_rusage
262 while True: 262 pid, status, last_rusage = _wait4(pid, options)
263 try:
264 pid, status, last_rusage = _wait4(pid, options)
265 except OSError:
266 if sys.exc_info()[1].errno != EINTR:
267 raise
268 else:
269 break
270 return pid, status 263 return pid, status
271 _waitpid = os.waitpid 264 _waitpid = os.waitpid
272 os.waitpid = waitpid_emu 265 os.waitpid = waitpid_emu
273 try: 266 try:
274 defaults = Popen._internal_poll.__func__.__defaults__ 267 defaults = Popen._internal_poll.__func__.__defaults__
296 def terminate(process): 289 def terminate(process):
297 try: 290 try:
298 process.terminate() 291 process.terminate()
299 except AttributeError: 292 except AttributeError:
300 os.kill(process.pid, SIGTERM) 293 os.kill(process.pid, SIGTERM)
294
295
296 # subprocess in Python 2.6- is not guarded against EINTR
297 try:
298 from errno import EINTR
299 except ImportError:
300 wait = Popen.wait
301 else:
302 def wait(process):
303 while True:
304 try:
305 return process.wait()
306 except OSError:
307 if sys.exc_info()[1].errno != EINTR:
308 raise