Whamcloud - gitweb
b=11564
[fs/lustre-release.git] / lustre / tests / leak_finder.pl
index 1a92327..5219996 100644 (file)
@@ -1,53 +1,89 @@
 #!/usr/bin/perl -w
 
+use IO::Handle;
+
+STDOUT->autoflush(1);
+STDERR->autoflush(1);
+
 my ($line, $memory);
 my $debug_line = 0;
 
+my $total = 0;
+my $max = 0;
+
 while ($line = <>) {
     $debug_line++;
     my ($file, $func, $lno, $name, $size, $addr, $type);
-    if ($line =~ m/^.*\((.*):(\d+):(.*)\(\) \d+\+\d+\): [vk](.*) '(.*)': (\d+) at (.*) \(tot .*$/) {
-        $file = $1;
-        $lno = $2;
-        $func = $3;
-        $type = $4;
-        $name = $5;
-        $size = $6;
-        $addr = $7;
+    if ($line =~ m/^.*(\.).*\((.*):(\d+):(.*)\(\)\) (k|v|slab-)(.*) '(.*)': (\d+) at (.*) \(tot (.*)\).*$/){
+        $file = $2;
+        $lno  = $3;
+        $func = $4;
+        $type = $6;
+        $name = $7;
+        $size = $8;
+        $addr = $9;
+        $tot  = $10;
+
+       # we can't dump the log after portals has exited, so skip "leaks"
+       # from memory freed in the portals module unloading.
+       if ($func eq 'portals_handle_init') {
+           next;
+       }
         printf("%8s %6d bytes at %s called %s (%s:%s:%d)\n", $type, $size,
                $addr, $name, $file, $func, $lno);
     } else {
         next;
     }
 
-    if ($type eq 'malloced') {
+    if (index($type, 'alloced') >= 0) {
+        if (defined($memory->{$addr})) {
+            print STDERR "*** Two allocs with the same address ($size bytes at $addr, $file:$func:$lno)\n";
+            print STDERR "    first malloc at $memory->{$addr}->{file}:$memory->{$addr}->{func}:$memory->{$addr}->{lno}, second at $file:$func:$lno\n";
+            next;
+        }
+
         $memory->{$addr}->{name} = $name;
         $memory->{$addr}->{size} = $size;
         $memory->{$addr}->{file} = $file;
         $memory->{$addr}->{func} = $func;
         $memory->{$addr}->{lno} = $lno;
         $memory->{$addr}->{debug_line} = $debug_line;
+
+        $total += $size;
+        if ($total > $max) {
+            $max = $total;
+        }
     } else {
         if (!defined($memory->{$addr})) {
-            print "*** Free without malloc ($size bytes at $addr, $file:$func:$lno)\n";
+            print STDERR "*** Free without malloc ($size bytes at $addr, $file:$func:$lno)\n";
             next;
         }
         my ($oldname, $oldsize, $oldfile, $oldfunc, $oldlno) = $memory->{$addr};
 
         if ($memory->{$addr}->{size} != $size) {
-            print "*** Free different size ($memory->{$addr}->{size} alloced, $size freed).\n";
-            print "    malloc at $memory->{$addr}->{file}:$memory->{$addr}->{func}:$memory->{$addr}->{lno}, free at $file:$func:$lno\n";
+            print STDERR "*** Free different size ($memory->{$addr}->{size} alloced, $size freed).\n";
+            print STDERR "    malloc at $memory->{$addr}->{file}:$memory->{$addr}->{func}:$memory->{$addr}->{lno}, free at $file:$func:$lno\n";
             next;
         }
 
         delete $memory->{$addr};
+        $total -= $size;
+    }
+    if ($total != int($tot)) {
+        print "kernel total $tot != my total $total\n";
+        $total = $tot;
     }
 }
 
+# Sort leak output by allocation time
+my @sorted = sort {
+    return $memory->{$a}->{debug_line} <=> $memory->{$b}->{debug_line};
+} keys(%{$memory});
+
 my $key;
-foreach $key (keys(%{$memory})) {
+foreach $key (@sorted) {
     my ($oldname, $oldsize, $oldfile, $oldfunc, $oldlno) = $memory->{$key};
-    print "*** Leak: $memory->{$key}->{size} bytes allocated at $key ($memory->{$key}->{file}:$memory->{$key}->{func}:$memory->{$key}->{lno}, debug file line $memory->{$key}->{debug_line})\n";
+    print STDERR "*** Leak: $memory->{$key}->{size} bytes allocated at $key ($memory->{$key}->{file}:$memory->{$key}->{func}:$memory->{$key}->{lno}, debug file line $memory->{$key}->{debug_line})\n";
 }
 
-print "Done.\n";
+print STDERR "maximum used: $max, amount leaked: $total\n";