Mercurial > ~astiob > upreckon > hgweb
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 |
