From 8899fd8dd1e848345c8e1399187f03b7008aa4af Mon Sep 17 00:00:00 2001 From: Thibault Saunier Date: Tue, 10 Nov 2015 17:43:54 +0100 Subject: validate: Implement support to run tests inside gdb Making debugging races leading to crashes easier to debug --- validate/launcher/baseclasses.py | 28 ++++++++++++++++++++++------ validate/launcher/main.py | 16 ++++++++++++++++ 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/validate/launcher/baseclasses.py b/validate/launcher/baseclasses.py index 7b0f2e1..6a4ef35 100644 --- a/validate/launcher/baseclasses.py +++ b/validate/launcher/baseclasses.py @@ -40,7 +40,7 @@ from utils import mkdir, Result, Colors, printc, DEFAULT_TIMEOUT, GST_SECOND, \ # The factor by which we increase the hard timeout when running inside # Valgrind -VALGRIND_TIMEOUT_FACTOR = 20 +GDB_TIMEOUT_FACTOR = VALGRIND_TIMEOUT_FACTOR = 20 # The error reported by valgrind when detecting errors VALGRIND_ERROR_CODE = 20 @@ -186,12 +186,19 @@ class Test(Loggable): def set_result(self, result, message="", error=""): self.debug("Setting result: %s (message: %s, error: %s)" % (result, message, error)) + if result is Result.TIMEOUT and self.options.debug is True: - pname = subprocess.check_output(("readlink -e /proc/%s/exe" - % self.process.pid).split(' ')).replace('\n', '') - raw_input("%sTimeout happened you can attach gdb doing: $gdb %s %d%s\n" - "Press enter to continue" % (Colors.FAIL, pname, self.process.pid, - Colors.ENDC)) + if self.options.gdb: + printc("Timeout, you should process c to get into gdb", + Colors.FAIL) + # and wait here until gdb exits + self.process.communicate() + else: + pname = subprocess.check_output(("readlink -e /proc/%s/exe" + % self.process.pid).split(' ')).replace('\n', '') + raw_input("%sTimeout happened you can attach gdb doing: $gdb %s %d%s\n" + "Press enter to continue" % (Colors.FAIL, pname, self.process.pid, + Colors.ENDC)) self.result = result self.message = message @@ -307,6 +314,12 @@ class Test(Loggable): def get_valgrind_suppressions(self): return [self.get_valgrind_suppression_file('data', 'gstvalidate.supp')] + def use_gdb(self): + if self.hard_timeout is not None: + self.hard_timeout *= GDB_TIMEOUT_FACTOR + self.timeout *= GDB_TIMEOUT_FACTOR + self.command = "gdb -ex run -ex quit --args %s" % self.command + def use_valgrind(self): vglogsfile = self.logfile + '.valgrind' self.extra_logfiles.append(vglogsfile) @@ -364,6 +377,9 @@ class Test(Loggable): self.proc_env[var] = self.proc_env.get(var, '') + os.pathsep + value self.add_env_variable(var, self.proc_env[var]) + if self.options.gdb: + self.use_gdb() + if self.options.valgrind: self.use_valgrind() diff --git a/validate/launcher/main.py b/validate/launcher/main.py index b1b8cc8..4ce4087 100644 --- a/validate/launcher/main.py +++ b/validate/launcher/main.py @@ -192,6 +192,7 @@ class LauncherConfig(Loggable): self.long_limit = utils.LONG_TEST self.config = None self.valgrind = False + self.gdb = False self.no_display = False self.xunit_file = None self.main_dir = utils.DEFAULT_MAIN_DIR @@ -230,6 +231,17 @@ class LauncherConfig(Loggable): else: self.output_dir = os.path.abspath(self.output_dir) + if self.gdb: + self.logsdir = "stdout" + self.debug = True + self.num_jobs = 1 + try: + subprocess.check_output("gdb --help", shell=True) + except subprocess.CalledProcessError: + printc("Want to use gdb, but not avalaible on the system", + Colors.FAIL) + return False + # other output directories if self.logsdir in ['stdout', 'stderr']: # Allow -l stdout/stderr to work like -rl stdout/stderr @@ -403,6 +415,10 @@ Note that all testsuite should be inside python modules, so the directory should parser.add_argument("-vg", "--valgrind", dest="valgrind", action="store_true", help="Run the tests inside Valgrind") + parser.add_argument("--gdb", dest="gdb", + action="store_true", + help="Run the tests inside gdb (implies" + " --output-dir=stdout and --jobs=1)") parser.add_argument("-nd", "--no-display", dest="no_display", action="store_true", help="Run the tests without outputting graphics" -- cgit v1.2.3