From: Simon Glass <sjg@chromium.org> Add a --malloc-dump option to the pytest framework that passes --malloc_dump to the sandbox binary. The filename may contain '%d' which is replaced with a sequence number that increments on each U-Boot restart, so each instance produces a separate dump. Override close() in ConsoleSandbox to send 'poweroff' before closing the PTY when --malloc-dump is active, so that state_uninit() runs and writes the dump file. Signed-off-by: Simon Glass <sjg@chromium.org> --- doc/develop/malloc.rst | 18 ++++++++++++++++++ test/py/conftest.py | 3 +++ test/py/console_sandbox.py | 26 ++++++++++++++++++++++++++ 3 files changed, 47 insertions(+) diff --git a/doc/develop/malloc.rst b/doc/develop/malloc.rst index b5c84c4c3bd..7e46c05dfde 100644 --- a/doc/develop/malloc.rst +++ b/doc/develop/malloc.rst @@ -511,6 +511,24 @@ by checking ``malloc_get_info()`` before and after:: allocations during the operation 6. Fix the leak and verify the test passes +**Dumping heap state on exit** + +When running sandbox, the ``--malloc_dump`` command-line option writes a heap +dump to a file when U-Boot exits cleanly (via ``poweroff`` or ``reset``). This +is useful for capturing heap state at the end of a test session:: + + ./u-boot -Tf -c "poweroff" --malloc_dump /tmp/heap.txt + +The pytest framework also supports this via ``--malloc-dump``:: + + test/py/test.py -B sandbox --malloc-dump /tmp/heap.txt -k test_source + +The filename may contain ``%d`` which is replaced with a sequence number +that increments each time U-Boot restarts during the test session, so each +instance produces a separate dump:: + + test/py/test.py -B sandbox --malloc-dump /tmp/heap%d.txt -k test_vboot + API Reference ------------- diff --git a/test/py/conftest.py b/test/py/conftest.py index f4c5e390a93..47a0d112e51 100644 --- a/test/py/conftest.py +++ b/test/py/conftest.py @@ -106,6 +106,8 @@ def pytest_addoption(parser): help='Disable console timeout (useful for debugging)') parser.addoption('--no-full', default=False, action='store_true', help='Skip flat-tree tests (run live-tree only)') + parser.addoption('--malloc-dump', default=None, + help='Write malloc dump to file on exit') def run_build(config, source_dir, build_dir, board_type, log): @@ -362,6 +364,7 @@ def pytest_configure(config): ubconfig.allow_exceptions = config.getoption('allow_exceptions') ubconfig.no_timeout = config.getoption('no_timeout') ubconfig.no_full = config.getoption('no_full') + ubconfig.malloc_dump = config.getoption('malloc_dump') env_vars = ( 'board_type', diff --git a/test/py/console_sandbox.py b/test/py/console_sandbox.py index 3bd109acef5..424e3ad2dd7 100644 --- a/test/py/console_sandbox.py +++ b/test/py/console_sandbox.py @@ -25,6 +25,7 @@ class ConsoleSandbox(ConsoleBase): super().__init__(log, config, max_fifo_fill=1024) self.sandbox_flags = [] self.use_dtb = True + self.malloc_dump_seq = 0 def get_spawn(self): """Connect to a fresh U-Boot instance. @@ -57,6 +58,14 @@ class ConsoleSandbox(ConsoleBase): if self.config.no_full: cmd.append('-F') + if self.config.malloc_dump: + try: + fname = self.config.malloc_dump % self.malloc_dump_seq + except TypeError: + fname = self.config.malloc_dump + self.malloc_dump_seq += 1 + cmd += ['--malloc_dump', fname] + # Always disable the pager cmd.append('-P') @@ -84,6 +93,23 @@ class ConsoleSandbox(ConsoleBase): self.sandbox_flags = [] self.use_dtb = True + def close(self): + """Terminate the sandbox, using poweroff for a clean shutdown. + + When --malloc-dump is active we need state_uninit() to run, so + send 'poweroff' instead of just closing the PTY. + """ + if self.p and self.config.malloc_dump: + try: + self.p.send('poweroff\n') + for _ in range(50): + if not self.p.isalive(): + break + time.sleep(0.1) + except: + pass + super().close() + def kill(self, sig): """Send a specific Unix signal to the sandbox process. -- 2.43.0