Detect valgrind memory leak reports; based on patch by Mathieu Lacage; closes bug #532
authorGustavo J. A. M. Carneiro <gjc@inescporto.pt>
Thu, 16 Apr 2009 16:47:02 +0100
changeset 4332 a1c7bc503a0c
parent 4331 771b9f0005d6
child 4333 89302376729e
child 4334 12b3fcf84fc5
Detect valgrind memory leak reports; based on patch by Mathieu Lacage; closes bug #532
regression.py
wscript
wutils.py
--- a/regression.py	Thu Apr 16 15:58:22 2009 +0200
+++ b/regression.py	Thu Apr 16 16:47:02 2009 +0100
@@ -159,13 +159,13 @@
             script = os.path.abspath(os.path.join('..', *os.path.split(program)))
             argv = [self.env['PYTHON'], script] + arguments
             try:
-                wutils.run_argv(argv, cwd=trace_output_path)
+                wutils.run_argv(argv, self.env, cwd=trace_output_path)
             except Utils.WafError, ex:
                 print >> sys.stderr, ex
                 return 1
         else:
             try:
-                wutils.run_program(program,
+                wutils.run_program(program, self.env,
                                    command_template=wutils.get_command_template(self.env, arguments),
                                    cwd=trace_output_path)
             except Utils.WafError, ex:
@@ -191,13 +191,13 @@
             script = os.path.abspath(os.path.join('..', *os.path.split(program)))
             argv = [self.env['PYTHON'], script] + arguments
             try:
-                retval = wutils.run_argv(argv, cwd=trace_output_path)
+                retval = wutils.run_argv(argv, self.env, cwd=trace_output_path)
             except Utils.WafError, ex:
                 print >> sys.stderr, ex
                 return 1
         else:
             try:
-                retval = wutils.run_program(program,
+                retval = wutils.run_program(program, self.env,
                                             command_template=wutils.get_command_template(self.env, arguments),
                                             cwd=trace_output_path)
             except Utils.WafError, ex:
--- a/wscript	Thu Apr 16 15:58:22 2009 +0200
+++ b/wscript	Thu Apr 16 16:47:02 2009 +0100
@@ -470,11 +470,11 @@
         lcov_report()
 
     if Options.options.run:
-        wutils.run_program(Options.options.run, wutils.get_command_template(env))
+        wutils.run_program(Options.options.run, env, wutils.get_command_template(env))
         raise SystemExit(0)
 
     if Options.options.pyrun:
-        wutils.run_python_program(Options.options.pyrun)
+        wutils.run_python_program(Options.options.pyrun, env)
         raise SystemExit(0)
 
     if Options.options.shell:
@@ -516,7 +516,7 @@
 
     if env['ENABLE_PYTHON_BINDINGS']:
         print "-- Running NS-3 Python bindings unit tests..."
-        wutils.run_argv([env['PYTHON'], os.path.join("utils", "python-unit-tests.py")], proc_env)
+        wutils.run_argv([env['PYTHON'], self.env, os.path.join("utils", "python-unit-tests.py")], proc_env)
     else:
         print "-- Skipping NS-3 Python bindings unit tests: Python bindings not enabled."
 
@@ -555,7 +555,7 @@
         shell = os.environ.get("SHELL", "/bin/sh")
 
     env = wutils.bld.env
-    wutils.run_argv([shell], {'NS3_MODULE_PATH': os.pathsep.join(env['NS3_MODULE_PATH'])})
+    wutils.run_argv([shell], env, {'NS3_MODULE_PATH': os.pathsep.join(env['NS3_MODULE_PATH'])})
 
 def doxygen():
     if not os.path.exists('doc/introspected-doxygen.h'):
--- a/wutils.py	Thu Apr 16 15:58:22 2009 +0200
+++ b/wutils.py	Thu Apr 16 16:47:02 2009 +0100
@@ -11,6 +11,7 @@
 import Logs
 import TaskGen
 import Build
+import re
 
 
 # these are set from the main wscript file
@@ -28,14 +29,7 @@
 
 
 def get_command_template(env, arguments=()):
-    if Options.options.valgrind:
-        if Options.options.command_template:
-            raise Utils.WafError("Options --command-template and --valgrind are conflicting")
-        if not env['VALGRIND']:
-            raise Utils.WafError("valgrind is not installed")
-        cmd = env['VALGRIND'] + " --leak-check=full --error-exitcode=1 %s"
-    else:
-        cmd = Options.options.command_template or '%s'
+    cmd = Options.options.command_template or '%s'
     for arg in arguments:
         cmd = cmd + " " + arg
     return cmd
@@ -120,9 +114,29 @@
 
     return proc_env
 
-def run_argv(argv, os_env=None, cwd=None):
+def run_argv(argv, env, os_env=None, cwd=None):
     proc_env = get_proc_env(os_env)
-    retval = subprocess.Popen(argv, env=proc_env, cwd=cwd).wait()
+    if Options.options.valgrind:
+        if Options.options.command_template:
+            raise Utils.WafError("Options --command-template and --valgrind are conflicting")
+        if not env['VALGRIND']:
+            raise Utils.WafError("valgrind is not installed")
+        argv = [env['VALGRIND'], "--leak-check=full", "--error-exitcode=1"] + argv
+        proc = subprocess.Popen(argv, env=proc_env, cwd=cwd, stderr=subprocess.PIPE)
+        reg = re.compile ('definitely lost: ([^ ]+) bytes')
+        error = False
+        for line in proc.stderr:
+            sys.stderr.write(line)
+            result = reg.search(line)
+            if result is None:
+                continue
+            if result.group(1) != "0":
+                error = True
+        retval = proc.wait()
+        if retval == 0 and error:
+            retval = 1
+    else:
+        retval = subprocess.Popen(argv, env=proc_env, cwd=cwd).wait()
     if retval:
         raise Utils.WafError("Command %s exited with code %i" % (argv, retval))
     return retval
@@ -169,7 +183,7 @@
         execvec = shlex.split(command_template % (program_node.abspath(env),))
     return program_name, execvec
 
-def run_program(program_string, command_template=None, cwd=None):
+def run_program(program_string, env, command_template=None, cwd=None):
     """
     if command_template is not None, then program_string == program
     name and argv is given by command_template with %s replaced by the
@@ -182,17 +196,17 @@
             cwd = Options.options.cwd_launch
         else:
             cwd = Options.cwd_launch
-    return run_argv(execvec, cwd=cwd)
+    return run_argv(execvec, env, cwd=cwd)
 
 
 
-def run_python_program(program_string):
+def run_python_program(program_string, env):
     env = bld.env
     execvec = shlex.split(program_string)
     if (Options.options.cwd_launch):
         cwd = Options.options.cwd_launch
     else:
         cwd = Options.cwd_launch
-    return run_argv([env['PYTHON']] + execvec, cwd=cwd)
+    return run_argv([env['PYTHON']] + execvec, env, cwd=cwd)