From patchwork Sat Mar 14 23:16:06 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1988 Return-Path: X-Original-To: u-boot-concept@u-boot.org Delivered-To: u-boot-concept@u-boot.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1773530272; bh=Nb86YYI8ZAn6Qj6EFy1GfPv5OYVQbQqa4WFXVPcEb+U=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=JzGi57IQZe6rKsIfsMAcymuBBbbo157OXrJHcfKrX44t98hIBClPme3twU1Z650Ao 5CMIF8YAoEAazv0KKhwkR4g+8X0YRDvL5TKC6axxEMnmeXztqQoV//Vle5C37KG7tf z3knAtmTX0Xd5F4bARBYTlWrU+AGw/VTUk9RgH9PClae+3j+z1e5vo/m/0W+LNKAPY ZicqidPv/p8a4uFmdmsY2Ty9JOq5Yoz4vrSQ03Ua3kAhX9iTJ/aDmNttIv0dLWsMRV x2m4NenmnLyYRo73tXrH5VbktOEVcKUO+4LxU4ow6PqRANufhNZ5FqKPmPbSQIDfaI KWHZwtLsU2YVw== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id C91486A042 for ; Sat, 14 Mar 2026 17:17:52 -0600 (MDT) X-Virus-Scanned: Debian amavis at Received: from mail.u-boot.org ([127.0.0.1]) by localhost (mail.u-boot.org [127.0.0.1]) (amavis, port 10024) with ESMTP id Oco0rdIA1b6Y for ; Sat, 14 Mar 2026 17:17:52 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1773530271; bh=Nb86YYI8ZAn6Qj6EFy1GfPv5OYVQbQqa4WFXVPcEb+U=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=CugH9Y/po1moOUMU0nJTo63s4qmmRh6tHkAbAvwwyaUDD5HXzsiajo3JD3LdXeO44 TCOgjujB8za6s8n06Q0pmC35bAFss3G+LGupqr4YUIZZ8V8UBsRPrBYFppb3cociBo EsgA0YnSWPCwUalgX3QrOlyNXU/0yeu24R6SHTlHZLnzDFc2/nO8/by5QT/vwqiHot tkJ3OV8eMFGEPzn+oeNVf2e5jgzE/Tv1t7QrbVA303R8Ttd0URJRKNcIIKRLzDWqGC O43gk8t6KkrPjUE39eVsT2rQix4tzfvAL/r/venpYkIGfXJAMhIjDLjkugRuwqhY+z 9W7XqAr8EoWwQ== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 27E386A046 for ; Sat, 14 Mar 2026 17:17:51 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1773530264; bh=OkxcP+ILq4se6hV6gq3JCZSESJRDM2GMM2OTIPVR0nA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=fJHy9y/k5P5qES3dKMywT4o1NnsIZN3VqQzVqUnhQpRMFvm7g+qZJ51nzOjAY8ofN LQEi45c9THl5W3RDudigLgAIKhP9NsUKkeYSuw82d5Oow7tOmrvw86PivZn9LcknAN 3Hei61XFLSJ/oBEIh1JMMgtJlJDRb91SvpPrbsyV0MMQNSmgZ6qthH41/mpFbqpm1r zwWuCVDdrlaCtSJlC6ITk1m2O8IxbLfjl4/zIS1usYzXGLMYMbMcuNFYn8vDy17qPM EzYOxjMA94ZeySIuyD/TNIULknx1tFbrYY3NEmaVElk+8o7FNF0lQ+2qq2GwmIcop9 CcBVaSjlL1hWQ== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 58B706A033; Sat, 14 Mar 2026 17:17:44 -0600 (MDT) X-Virus-Scanned: Debian amavis at Received: from mail.u-boot.org ([127.0.0.1]) by localhost (mail.u-boot.org [127.0.0.1]) (amavis, port 10026) with ESMTP id YH25zUiqtObG; Sat, 14 Mar 2026 17:17:44 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1773530263; bh=loK6hRgLFQ6XjZeuNywCGaKboZ/LQxQ7HuE89JVbNm4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=czzkmMdeeTudfULUhIQ4SGF5JgsPRCAWO+P3Z6QbNF9F62S2H/3PT0mLq2UfZi+ET rMzf19VBItk/hBTEYJcc7VamXorRBgaLq4P3+NH8tv/v2QMSbJz/C2qRUXJgI0anSy bcHTOH1w8ySjTCPc5EozriZbLtexctQqL/A+YdYPAdj1HDQ0esffGO1fpyD+Ay/ECW o6/4zARI8Bhq+eoGgN86NBJydwZzQE/dS7aXOppRDyvUY9Uz/OIdpkUlQYKe3MLYC4 VAG8j0iDnscIZC3OxPWWOVLNUrAUNYbn6v+5Xfc8gzGkGBPPiEawbRTfUjg2C5kwr+ t9rAW2XDjkCeg== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id AEE986A037; Sat, 14 Mar 2026 17:17:43 -0600 (MDT) From: Simon Glass To: U-Boot Concept Date: Sat, 14 Mar 2026 17:16:06 -0600 Message-ID: <20260314231618.338113-16-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260314231618.338113-1-sjg@u-boot.org> References: <20260314231618.338113-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: 6Q2QYX3WZRVT65I4SUR3J272OEUT7CKE X-Message-ID-Hash: 6Q2QYX3WZRVT65I4SUR3J272OEUT7CKE X-MailFrom: sjg@u-boot.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: Simon Glass X-Mailman-Version: 3.3.10 Precedence: list Subject: [Concept] [PATCH 15/19] test: py: Add --malloc-dump support to pytest List-Id: Discussion and patches related to U-Boot Concept Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: Simon Glass 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 --- 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.