Merge "Add timeout handler when running on the bots"
diff --git a/build.gradle b/build.gradle
index ec00f11..64f09d7 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1343,6 +1343,9 @@
println "Start executing test ${desc.name} [${desc.className}]"
}
afterTest { desc, result ->
+ if (project.hasProperty('update_test_timestamp')) {
+ file(project.getProperty('update_test_timestamp')).text = new Date().getTime()
+ }
println "Done executing test ${desc.name} [${desc.className}] with result: ${result.resultType}"
}
}
diff --git a/tools/archive.py b/tools/archive.py
index ad58bca..013ff15 100755
--- a/tools/archive.py
+++ b/tools/archive.py
@@ -79,7 +79,7 @@
return GetVersionDestination('http://storage.googleapis.com/', '', is_master)
def Main():
- if not 'BUILDBOT_BUILDERNAME' in os.environ:
+ if utils.is_bot():
raise Exception('You are not a bot, don\'t archive builds')
# Generate an r8-ed build without dependencies.
diff --git a/tools/test.py b/tools/test.py
index e4433b3..d9dca9f 100755
--- a/tools/test.py
+++ b/tools/test.py
@@ -12,6 +12,8 @@
import optparse
import subprocess
import sys
+import thread
+import time
import utils
import notify
@@ -25,6 +27,14 @@
"4.4.4",
"4.0.4"]
+# How often do we check for progress on the bots:
+# Should be long enough that a normal run would always have med progress
+# Should be short enough that we ensure that two calls are close enough
+# to happen before bot times out.
+# A false positiv, i.e., printing the stacks of non hanging processes
+# is not a problem, no harm done except some logging in the stdout.
+TIMEOUT_HANDLER_PERIOD = 60 * 18
+
def ParseOptions():
result = optparse.OptionParser()
result.add_option('--no-internal', '--no_internal',
@@ -95,7 +105,7 @@
def Main():
(options, args) = ParseOptions()
- if 'BUILDBOT_BUILDERNAME' in os.environ:
+ if utils.is_bot():
gradle.RunGradle(['clean'])
# Build R8lib with dependencies for bootstrapping tests before adding test sources
@@ -171,6 +181,12 @@
'%s.tar.gz' % sha1)
utils.unpack_archive('%s.tar.gz' % sha1)
+ if utils.is_bot() and not utils.IsWindows():
+ timestamp_file = os.path.join(utils.BUILD, 'last_test_time')
+ if os.path.exists(timestamp_file):
+ os.remove(timestamp_file)
+ gradle_args.append('-Pupdate_test_timestamp=' + timestamp_file)
+ thread.start_new_thread(timeout_handler, (timestamp_file,))
# Now run tests on selected runtime(s).
vms_to_test = [options.dex_vm] if options.dex_vm != "all" else ALL_ART_VMS
@@ -193,6 +209,45 @@
return 0
+
+def print_jstacks():
+ processes = subprocess.check_output(['ps', 'aux'])
+ for l in processes.splitlines():
+ if 'java' in l and 'openjdk' in l:
+ # Example line:
+ # ricow 184313 2.6 0.0 36839068 31808 ? Sl 09:53 0:00 /us..
+ columns = l.split()
+ pid = columns[1]
+ return_value = subprocess.call(['jstack', pid])
+ if return_value:
+ print('Could not jstack %s' % l)
+ print('----') # May be eaten by gradle prints.
+ print('----') # May be eaten by gradle prints.
+
+def get_time_from_file(timestamp_file):
+ if os.path.exists(timestamp_file):
+ timestamp = os.stat(timestamp_file).st_mtime
+ print('TIMEOUT HANDLER timestamp: %s' % (timestamp))
+ print('---') # May be eaten by gradle prints.
+ print('---') # May be eaten by gradle prints.
+ sys.stdout.flush()
+ return timestamp
+ else:
+ print('TIMEOUT HANDLER no timestamp file yet')
+ print('---') # May be eaten by gradle prints.
+ print('---') # May be eaten by gradle prints.
+ sys.stdout.flush()
+ return None
+
+def timeout_handler(timestamp_file):
+ last_timestamp = None
+ while True:
+ time.sleep(TIMEOUT_HANDLER_PERIOD)
+ new_timestamp = get_time_from_file(timestamp_file)
+ if last_timestamp and new_timestamp == last_timestamp:
+ print_jstacks()
+ last_timestamp = new_timestamp
+
if __name__ == '__main__':
return_code = Main()
if return_code != 0:
diff --git a/tools/utils.py b/tools/utils.py
index d2c4935..5355ba8 100644
--- a/tools/utils.py
+++ b/tools/utils.py
@@ -313,3 +313,6 @@
def get_android_jar(api):
return os.path.join(REPO_ROOT, ANDROID_JAR.format(api=api))
+
+def is_bot():
+ return 'BUILDBOT_BUILDERNAME' in os.environ