Bug 792: Neither test.py nor waf --valgrind catch all kinds of memory leaks
authorCraig Dowell <craigdo@ee.washington.edu>
Tue, 19 Jan 2010 16:56:44 +0100
changeset 5917 aa8364846523
parent 5916 8f94a0ca3964
child 5918 a0e24e8844da
Bug 792: Neither test.py nor waf --valgrind catch all kinds of memory leaks
test.py
wutils.py
--- a/test.py	Mon Jan 18 10:00:46 2010 +0100
+++ b/test.py	Tue Jan 19 16:56:44 2010 +0100
@@ -671,7 +671,8 @@
     suppressions_path = os.path.join (base, VALGRIND_SUPPRESSIONS_FILE)
     path_cmd = os.path.join (NS3_BUILDDIR, NS3_ACTIVE_VARIANT, shell_command)
     if valgrind:
-        cmd = "valgrind --suppressions=%s --leak-check=full --show-reachable=yes --error-exitcode=2 %s" % (suppressions_path, path_cmd)
+        cmd = "valgrind --suppressions=%s --leak-check=full --show-reachable=yes --error-exitcode=2 %s" % (suppressions_path, 
+            path_cmd)
     else:
         cmd = path_cmd
 
@@ -680,21 +681,23 @@
 
     start_time = time.time()
     proc = subprocess.Popen(cmd, shell = True, cwd = directory, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+    stdout_results, stderr_results = proc.communicate()
     elapsed_time = time.time() - start_time
-    ##detect errors ignored by valgrind
-    error = False
-    if valgrind:
-      reg = re.compile ('still reachable: ([^ ]+) bytes')
-      for line in proc.stderr:
-          result = reg.search(line)
-          if result is None:
-              continue
-          if result.group(1) != "0":
-             error = True
-    stdout_results, stderr_results = proc.communicate()
+
     retval = proc.returncode
-    if retval == 0 and error:
-        retval = 1
+
+    #
+    # valgrind sometimes has its own idea about what kind of memory management
+    # errors are important.  We want to detect *any* leaks, so the way to do 
+    # that is to look for the presence of a valgrind leak summary section.
+    #
+    # If another error has occurred (like a test suite has failed), we don't 
+    # want to trump that error, so only do the valgrind output scan if the 
+    # test has otherwise passed (return code was zero).
+    #
+    if valgrind and retval == 0 and "== LEAK SUMMARY:" in stderr_results:
+        retval = 2
+    
     if options.verbose:
         print "Return code = ", retval
         print "stderr = ", stderr_results
--- a/wutils.py	Mon Jan 18 10:00:46 2010 +0100
+++ b/wutils.py	Tue Jan 19 16:56:44 2010 +0100
@@ -121,16 +121,12 @@
             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
+        argv = [env['VALGRIND'], "--leak-check=full", "--show-reachable=yes", "--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":
+            if "== LEAK SUMMARY" in line:
                 error = True
         retval = proc.wait()
         if retval == 0 and error: