# HG changeset patch # User Oleg Oshmyan # Date 1305510804 -3600 # Node ID f5b8a0c0e3cbedd2d837ec07a8a95aa0e22569cf # Parent fcdcd0c95552d1d8b2b23d82da0406faf4cd70ea Multiple bug fixes in the unix module Bug fix: a fatal OSError could occur inside Popen.poll() inside unix.call(). Bug fix: CPU-time-wise-ultra-fast testees no longer cause negative zero times to be reported on UNIX. Bug fix (regression in 16fe21d6582e): stdin is no longer read to check for Escape presses when it is not available for reading on UNIX. This would cause Upreckon to block until a key was pressed or, if the testee exceeded the wall-clock time limit, until the testee exit. Bug fix: unix.call() now works on Python 3.2. Bug fix: a fatal RuntimeError no longer occurs on problems with memory limits on systems with RLIMIT_VMEM but no RLIMIT_AS. diff -r fcdcd0c95552 -r f5b8a0c0e3cb unix.py --- a/unix.py Sun May 15 23:14:00 2011 +0100 +++ b/unix.py Mon May 16 02:53:24 2011 +0100 @@ -51,11 +51,6 @@ from fcntl import fcntl, F_SETFD, F_GETFD, F_SETFL, F_GETFL from os import O_NONBLOCK try: - from signal import siginterrupt - except ImportError: - # Sucks. - siginterrupt = lambda signalnum, flag: None - try: import cPickle as pickle except ImportError: import pickle @@ -93,6 +88,12 @@ FD_CLOEXEC = 1 try: + from signal import siginterrupt + except ImportError: + # Sucks. + siginterrupt = lambda signalnum, flag: None + + try: from resource import getrusage, RUSAGE_SELF, RUSAGE_CHILDREN except ImportError: from time import clock as cpuclock @@ -107,7 +108,7 @@ try: from resource import RLIMIT_AS except ImportError: - from resource import RLIMIT_VMEM + from resource import RLIMIT_VMEM as RLIMIT_AS except ImportError: setrlimit = None @@ -147,6 +148,14 @@ # passing between the calls to fork and exec to be counted in os.write(write, pickle.dumps((clock(), cpuclock()), 1)) kwargs['preexec_fn'] = preexec_fn + # So how the hell do I actually make use of pass_fds? + # On 3.1-, calling Popen with pass_fds prints an exception + # from Popen.__del__ to stderr. On 3.2, Popen without close_fds + # or pass_fds creates a child and fails but that of course + # generates a SIGCHLD, which causes problems, and I have + # no process ID to wait upon to negate the changes made + # by the SIGCHLD handler. + kwargs['close_fds'] = False old_rusage = getrusage(RUSAGE_CHILDREN) last_rusage = None while True: @@ -183,7 +192,7 @@ try: while case.process.poll() is None: s = select((sys.stdin, sigchld_pipe_read), (), ()) - if (sigchld_pipe_read not in s[0] and + if (s[0] == [sys.stdin] and sys.stdin.read(1) == '\33'): raise testcases.CanceledByUser except (SelectError, IOError): @@ -199,7 +208,7 @@ if remaining > 0: s = select((sys.stdin, sigchld_pipe_read), (), (), remaining) - if (sigchld_pipe_read not in s[0] and + if (s[0] == [sys.stdin] and sys.stdin.read(1) == '\33'): raise testcases.CanceledByUser else: @@ -220,6 +229,9 @@ if new_rusage: time_started = old_rusage.ru_utime + old_rusage.ru_stime + cpustart time_stopped = new_rusage.ru_utime + new_rusage.ru_stime + # Yes, this actually happens + if time_started > time_stopped: + time_started = time_stopped if case.maxcputime or not case.maxwalltime: case.time_started = time_started case.time_stopped = time_stopped @@ -247,7 +259,14 @@ try: def waitpid_emu(pid, options, _wait4=os.wait4): global last_rusage - pid, status, last_rusage = _wait4(pid, options) + while True: + try: + pid, status, last_rusage = _wait4(pid, options) + except OSError: + if sys.exc_info()[1].errno != EINTR: + raise + else: + break return pid, status _waitpid = os.waitpid os.waitpid = waitpid_emu