changeset 127:f5b8a0c0e3cb

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.
author Oleg Oshmyan <chortos@inbox.lv>
date Mon, 16 May 2011 02:53:24 +0100
parents fcdcd0c95552
children 42c8f5c152a5
files unix.py
diffstat 1 files changed, 28 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- 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