diff testcases.py @ 63:fb9d0223a871

Fixed negative run times reported on POSIX
author Oleg Oshmyan <chortos@inbox.lv>
date Wed, 22 Dec 2010 18:56:25 +0200
parents 593ad09cd69b
children fcb5ab97f08e
line wrap: on
line diff
--- a/testcases.py	Wed Dec 22 15:03:47 2010 +0200
+++ b/testcases.py	Wed Dec 22 18:56:25 2010 +0200
@@ -92,6 +92,7 @@
 	from signal import SIGCHLD, signal, SIG_DFL
 	from select import select, error as select_error
 	from errno import EINTR
+	import pickle
 except ImportError:
 	try:
 		from _subprocess import WAIT_OBJECT_0, STD_INPUT_HANDLE, INFINITE
@@ -184,47 +185,61 @@
 	# If you want this to work, don't set any stdio argument to PIPE
 	def call_real(*args, **kwargs):
 		bury_child.case = case = kwargs.pop('case')
+		preexec_fn_ = kwargs.get('preexec_fn', None)
+		read, write = os.pipe()
+		def preexec_fn():
+			os.close(read)
+			if preexec_fn_:
+				preexec_fn_()
+			os.write(write, pickle.dumps(clock(), 1))
+		kwargs['preexec_fn'] = preexec_fn
 		try:
 			case.process = Popen(*args, **kwargs)
 		except OSError:
+			os.close(read)
 			raise CannotStartTestee(sys.exc_info()[1])
-		case.time_started = clock()
-		if pause is None:
-			if case.maxtime:
-				time.sleep(case.maxtime)
-				if case.process.poll() is None:
-					raise TimeLimitExceeded
+		finally:
+			os.close(write)
+		try:
+			if pause is None:
+				if case.maxtime:
+					time.sleep(case.maxtime)
+					if case.process.poll() is None:
+						raise TimeLimitExceeded
+				else:
+					case.process.wait()
 			else:
-				case.process.wait()
-		else:
-			if not case.maxtime:
-				try:
-					while case.process.poll() is None:
-						if select((sys.stdin,), (), ())[0]:
-							if sys.stdin.read(1) == '\33':
-								raise CanceledByUser
-				except select_error:
-					if sys.exc_info()[1].args[0] != EINTR:
-						raise
-					else:
-						case.process.poll()
-			else:
-				time_end = clock() + case.maxtime
-				try:
-					while case.process.poll() is None:
-						remaining = time_end - clock()
-						if remaining > 0:
-							if select((sys.stdin,), (), (), remaining)[0]:
+				if not case.maxtime:
+					try:
+						while case.process.poll() is None:
+							if select((sys.stdin,), (), ())[0]:
 								if sys.stdin.read(1) == '\33':
 									raise CanceledByUser
+					except select_error:
+						if sys.exc_info()[1].args[0] != EINTR:
+							raise
 						else:
-							raise TimeLimitExceeded
-				except select_error:
-					if sys.exc_info()[1].args[0] != EINTR:
-						raise
-					else:
-						case.process.poll()
-		del bury_child.case
+							case.process.poll()
+				else:
+					time_end = clock() + case.maxtime
+					try:
+						while case.process.poll() is None:
+							remaining = time_end - clock()
+							if remaining > 0:
+								if select((sys.stdin,), (), (), remaining)[0]:
+									if sys.stdin.read(1) == '\33':
+										raise CanceledByUser
+							else:
+								raise TimeLimitExceeded
+					except select_error:
+						if sys.exc_info()[1].args[0] != EINTR:
+							raise
+						else:
+							case.process.poll()
+		finally:
+			case.time_started = pickle.loads(os.read(read, 512))
+			os.close(read)
+			del bury_child.case
 	def call(*args, **kwargs):
 		if 'preexec_fn' in kwargs:
 			try: