[PATCH 12/12] tests: run kmemleak between tests if available
Andrei Otcheretianski
andrei.otcheretianski at intel.com
Mon Dec 25 02:21:09 PST 2023
From: Benjamin Berg <benjamin.berg at intel.com>
This triggers a kmemleak scan between tests. This allows finding memory
leaks and doing this should attribute the leak to the correct test in
most cases. Note that it does add a sleep after each test, as such it is
most sensible when combined with UML time-travel.
Signed-off-by: Benjamin Berg <benjamin.berg at intel.com>
---
tests/hwsim/run-tests.py | 54 ++++++++++++++++++++++++++++++++++++++--
1 file changed, 52 insertions(+), 2 deletions(-)
diff --git a/tests/hwsim/run-tests.py b/tests/hwsim/run-tests.py
index 30368a97ab..1a23e0addf 100755
--- a/tests/hwsim/run-tests.py
+++ b/tests/hwsim/run-tests.py
@@ -123,11 +123,12 @@ def report(conn, prefill, build, commit, run, test, result, duration, logdir,
logdir + "/" + test + "." + log)
class DataCollector(object):
- def __init__(self, logdir, testname, args):
+ def __init__(self, logdir, testname, kmemleak, args):
self._logdir = logdir
self._testname = testname
self._tracing = args.tracing
self._dmesg = args.dmesg
+ self._kmemleak = kmemleak
self._dbus = args.dbus
def __enter__(self):
if self._tracing:
@@ -159,6 +160,36 @@ class DataCollector(object):
self._trace_cmd.stdin.write(b'DONE\n')
self._trace_cmd.stdin.flush()
self._trace_cmd.wait()
+
+ if self._kmemleak:
+ output = os.path.join(self._logdir, '%s.kmemleak' % (self._testname, ))
+ num = 0
+ while os.path.exists(output):
+ output = os.path.join(self._logdir, '%s.kmemleak-%d' % (self._testname, num))
+ num += 1
+
+ # Trigger kmemleak
+ with open('/sys/kernel/debug/kmemleak', 'w+') as kmemleak:
+ kmemleak.write('scan')
+ kmemleak.seek(0)
+
+ # Minimum reporting age
+ time.sleep(5)
+
+ kmemleak.write('scan')
+ kmemleak.seek(0)
+
+ leaks = []
+ while l := kmemleak.read():
+ leaks.append(l)
+ leaks = ''.join(leaks)
+ if leaks:
+ with open(output, 'w') as out:
+ out.write(leaks)
+
+ kmemleak.seek(0)
+ kmemleak.write('clear')
+
if self._dmesg:
output = os.path.join(self._logdir, '%s.dmesg' % (self._testname, ))
num = 0
@@ -395,6 +426,19 @@ def main():
if args.dmesg:
subprocess.call(['dmesg', '-c'], stdout=open('/dev/null', 'w'))
+ try:
+ # try to clear out any leaks that happened earlier
+ with open('/sys/kernel/debug/kmemleak', 'w') as kmemleak:
+ kmemleak.write('scan')
+ kmemleak.seek(0)
+ time.sleep(5)
+ kmemleak.write('scan')
+ kmemleak.seek(0)
+ kmemleak.write('clear')
+ have_kmemleak = True
+ except OSError:
+ have_kmemleak = False
+
if conn and args.prefill:
for t in tests_to_run:
name = t.__name__.replace('test_', '', 1)
@@ -494,7 +538,7 @@ def main():
pass
reset_ok = True
- with DataCollector(args.logdir, name, args):
+ with DataCollector(args.logdir, name, have_kmemleak, args):
count = count + 1
msg = "START {} {}/{}".format(name, count, num_tests)
logger.info(msg)
@@ -651,6 +695,12 @@ def main():
logger.info("Kernel issue found in dmesg - mark test failed")
result = 'FAIL'
+ if result == 'PASS' and have_kmemleak:
+ # The file is only created if a leak was found
+ if os.path.exists(os.path.join(args.logdir, name + '.kmemleak')):
+ logger.info("Kernel memory leak found - mark test failed")
+ result = 'FAIL'
+
if result == 'PASS':
passed.append(name)
elif result == 'SKIP':
--
2.43.0
More information about the Hostap
mailing list