From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-dy1-f179.google.com (mail-dy1-f179.google.com [74.125.82.179]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5E87D3E3141 for ; Sat, 17 Oct 2026 12:24:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.179 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792239849; cv=none; b=OuTXFztxAg+Amh0ioRWn6ZM6EGCVU4T91R9/HoPwYDwVBGo7r3pciMnPBJb1WnVhLvyQ2+tjNMHLruefDwA7qEpuQapeRkwp6RZ/5licy738Rp6eFRQpfgjxvutjZ/K4ar+0CX6tBRcTA9+l7Fs/3381vWfgBuLGLHTf4fdEDcA= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792239849; c=relaxed/simple; bh=Mx1XA5NXVS41t1VlcXaf7+JjFJSkrUsfufwSRgTXzFk=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=aJlQ3IFLLAbjfscmhcNvv4ORpnCcIUp4s9sLbdYjybebB7gpu5U/m5sCSBzGl5rmZTkcO4zJLK1NLDkdA9Erln5O9vf6w+iFWZF0eO+9W7jma0IdMWEf4HBflU6EyMrwwKHuvBJup2pmW39nmUqCgsa7Vi96qQAc7WYGFi63ebw= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=DtSoL+Zd; arc=none smtp.client-ip=74.125.82.179 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="DtSoL+Zd" Received: by mail-dy1-f179.google.com with SMTP id 5a478bee46e88-35ef6b49813so1452117eec.0 for ; Sat, 17 Oct 2026 05:24:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792239847; x=1792844647; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:to :from:from:to:cc:subject:date:message-id:reply-to:content-type; bh=DAnHTt2+8d0T/aZD8Hjx52zgcZ6OdYhqhoW7qqJP0gY=; b=DtSoL+Zdn5VDlbcWwmVAjkd/RoYuSmB7yKpuiCI5YuevdKGaewxPAN8/mp2NAjWX48 OyWlQOOmT4ZQpKLDmPLS6u46ot/Aih/EXjEzbohp/82+8QSI4WDT3aUqvfwTd6uOUxCd moN4+RI0WjweGuTHTIlwjLlen8W1S//punGN9a6FEnhUadpueTyQAhYtNQd1X5uN3vVU mz7MKIF7Gu66+ebprbvPs9LXTJd98a6T7p2OktAlpbLtZeq943eco09JieFswwI+Jnl/ SVlPUVh4Ms36yp++/II6MlcfsZUXy1tpr2U9qougsRflPbWxLhTEejL3dEu2J258Leh1 E7Aw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792239847; x=1792844647; h=content-transfer-encoding:mime-version:message-id:date:subject:to :from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to:content-type; bh=DAnHTt2+8d0T/aZD8Hjx52zgcZ6OdYhqhoW7qqJP0gY=; b=n9GvNnA72+eo0lcy4bNvPy/Ra97tSxokzWSu0OIVCGKDHuFOYl4q551EF3jVLqI800 H7f5SkQWeG0wWkY2u7tbTN+/cC+n99p0l+0b2K/j3pkgy7jqr4LD+Iobi5g9zi7Sa+b5 DcI2FMITdtseRQXhb6iRfkHZCI+yiMXa53oyjcflVW48vKyqqUMLXfHFpl7nI6v7pYfs juDA3gao2oji2vcgjBsJA/7rxa2UlbSf9jnqx30XXDIDhjsAvcksY7S1Mb2SFJ/GzejQ 0WvnuasTLoDs90Mo9HlgbowHsKw0waM5Vw8PQYVWzWyeM47Pgc09CE+4YJ26qQcpmT8M 0CKA== X-Gm-Message-State: AFq9FYJlHUv+I8ZmpzqXDS0yUkFgiZZSTGdh5JhvXL4xg87OPI6+sB89 gH09TsK7ycw60l3RHEwZ1869SHCnihnWmulrQOc2x9uJYAsUwoQJl5IfFlRnb3s1 X-Gm-Gg: AYBFou1wCWbuQ6VqTfAeYcDPggYIozZ7oGggIHFQMAcNIvc4OaEi153RRujzg5BdlOo IudzzJ81A4SpQxmTvWnouwxA75cCXMPCXOHVleo3g49fR7d5K41I3lU/L9X/SYRVcek+PyoXtLo HGZJajgxqXJce1F2NSFgQEc1okUkvCO+r3mBMErLJ9PRMfSHf75J+DDzuRYHEx7lHofjXcpE1bO PL6anTy/oirwPu/5Mfq2xqWNh6FmCcNoTmE9J04rwKU8xcLNifrwZ69nlzpPchaEeW20CX7Q1Lv dy/uGD4sC6mwsGr6ciO5Gzi+E5klmxU/6itRXuKYYShpZbLtAr2ONn7wNCMfcuTubEK6cTsrQBA aZjPuOrvQwDbXntyMBsvuxNeulq5RyJlWMwnghqQyYBssVEd82rbyPHsZOiPQf5oY0C4k1fpx2f /EvFGoolsJePViQotbw+xotSzLdd8irpKgQ319fYSDDq/d8PbTnSKbwW3yE06iM093gIYLANyLV r+obP3iRfXA9wqYbcpxMswdmuG2u/umOsaY7GDaQRkIz+w= X-Received: by 2002:a05:7301:7305:b0:34e:9923:e372 with SMTP id 5a478bee46e88-361a2b35aefmr3445131eec.29.1792239847184; Sat, 17 Oct 2026 05:24:07 -0700 (PDT) Received: from chaosheng-ASUS-TUF-Gaming-F16-FX607JV-FX607JV.lan ([183.242.161.82]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-360819bc569sm14724539eec.11.2026.10.17.05.24.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 17 Oct 2026 05:24:06 -0700 (PDT) From: Chaosheng Qu To: linux-trace-kernel@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH] rtla: add tests for tracefs instance cleanup Date: Sat, 17 Oct 2026 20:23:59 +0800 Message-ID: <20261017122359.402696-1-chaosheng.qu.linux@gmail.com> X-Mailer: git-send-email 2.43.0 Precedence: bulk X-Mailing-List: linux-trace-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit rtla creates a tracefs instance per run (osnoise_top, osnoise_hist, timerlat_top, timerlat_hist) and is expected to remove it again on the way out. Nothing verifies that today, so a cleanup regression would only show up as a confusing failure of the *next* run: tracefs_instance_create() can fail with -EEXIST, and an interrupted run can leave stale tracer state behind. tests/engine.sh already works around this by rmdir-ing leftover instances before every test ("remove any dangling instances created by improperly exited rtla runs"), which shows the gap is known but untested. Add a test for the abnormal-exit paths that are actually hit in practice: - SIGINT during a run (interactive Ctrl-C) - rtla's own -d/--duration timer - a failing --on-threshold shell action - several interrupted runs in a row, followed by a normal run These need rtla running in the background while the test signals it, which engine.sh's check() (a single foreground command) cannot express, so the new cleanup.t drives a helper script and emits TAP itself. SIGTERM is covered too, but reported as a TAP TODO comment: rtla installs handlers for SIGINT and SIGALRM only, so SIGTERM terminates the process without running the cleanup path and leaks the instance. Keeping it visible rather than turning it into a pass means a future regression in the paths that *do* work is still caught. Once SIGTERM is handled, drop the TODO comment and the case becomes a plain assertion. The test needs root, tracefs and CONFIG_OSNOISE_TRACER, and skips cleanly when tracefs is not mounted writable. Signed-off-by: Chaosheng Qu --- tools/tracing/rtla/tests/cleanup.t | 55 ++++++ .../rtla/tests/scripts/check-cleanup.sh | 187 ++++++++++++++++++ 2 files changed, 242 insertions(+) create mode 100755 tools/tracing/rtla/tests/cleanup.t create mode 100755 tools/tracing/rtla/tests/scripts/check-cleanup.sh diff --git a/tools/tracing/rtla/tests/cleanup.t b/tools/tracing/rtla/tests/cleanup.t new file mode 100755 index 000000000000..46e69c191792 --- /dev/null +++ b/tools/tracing/rtla/tests/cleanup.t @@ -0,0 +1,55 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# +# Verify that rtla removes the tracefs instance it created on the abnormal +# exit paths users actually hit: +# +# - SIGINT during a run (interactive Ctrl-C) +# - rtla's own -d/--duration timer +# - a failing --on-threshold shell action +# - several interrupted runs in a row, followed by a normal run +# +# A leaked instance pollutes the next invocation, so this is worth pinning +# down in CI. The SIGTERM case is reported as a TAP TODO comment because +# rtla does not install a SIGTERM handler yet. +source tests/engine.sh +test_begin + +set_timeout 2m + +# +# These cases need to run rtla in the background and signal it, which +# engine.sh's check() (one foreground command) cannot express. +# +run_cleanup_cases() { + local helper="$testdir/scripts/check-cleanup.sh" + local out rc + + ctr=$((ctr + 1)) + [ -z "$TEST_COUNT" ] && return + + if [ ! -x "$helper" ]; then + echo "not ok $ctr - cleanup helper is not executable" + return + fi + + out=$("$helper" "$RTLA" 2>&1) + rc=$? + if [ $rc -eq 0 ]; then + # Surface known issues as TAP comments so they stay visible + # even when the case passes. + printf '%s\n' "$out" | grep '^TODO: ' | while read -r line; do + echo "# ${line#TODO: }" + done + echo "ok $ctr - instances cleaned up on SIGINT, timeout and action failure" + else + echo "not ok $ctr - instances cleaned up on SIGINT, timeout and action failure" + printf '%s\n' "$out" | while read -r line; do + echo "# $line" + done + fi +} + +run_cleanup_cases + +test_end diff --git a/tools/tracing/rtla/tests/scripts/check-cleanup.sh b/tools/tracing/rtla/tests/scripts/check-cleanup.sh new file mode 100755 index 000000000000..1ead5ce3c517 --- /dev/null +++ b/tools/tracing/rtla/tests/scripts/check-cleanup.sh @@ -0,0 +1,187 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# +# Verify that rtla removes the tracefs instances it created, even when it is +# interrupted (SIGINT/SIGTERM), killed by its own timeout, or when a shell +# action fails. +# +# This is a *test* for tools/tracing/rtla; it does not change rtla behaviour. +# +# Requires: root, tracefs mounted at /sys/kernel/tracing, CONFIG_OSNOISE_TRACER. +# Usage: rtla_cleanup_test.sh /path/to/rtla + +RTLA=${1:-rtla} +TRACEFS=/sys/kernel/tracing +INSTANCES=$TRACEFS/instances +FAIL=0 +PASS=0 + +log() { printf '%s\n' "$*"; } +pass() { PASS=$((PASS+1)); log "PASS: $*"; } +fail() { FAIL=$((FAIL+1)); log "FAIL: $*"; } +todo() { TODO_N=$((TODO_N+1)); log "TODO: $*"; } +TODO_N=0 + +cleanup_all() { + for i in osnoise_top osnoise_hist timerlat_top timerlat_hist hwnoise_top; do + [ -d "$INSTANCES/$i" ] && rmdir "$INSTANCES/$i" 2>/dev/null + done +} + +# Wait up to $2 ms for $1 to disappear. +wait_gone() { + _path=$1 + _ms=${2:-5000} + _i=0 + while [ -d "$_path" ] && [ $_i -lt $_ms ]; do + sleep 0.05 + _i=$((_i+50)) + done + [ ! -d "$_path" ] +} + +# Wait until $1 exists (up to $2 ms). +wait_present() { + _path=$1 + _ms=${2:-10000} + _i=0 + while [ ! -d "$_path" ] && [ $_i -lt $_ms ]; do + sleep 0.05 + _i=$((_i+50)) + done + [ -d "$_path" ] +} + +check_instances_absent() { + _desc=$1 + _left="" + for i in osnoise_top osnoise_hist timerlat_top timerlat_hist; do + [ -d "$INSTANCES/$i" ] && _left="$_left $i" + done + if [ -z "$_left" ]; then + pass "$_desc: no leftover instance" + else + fail "$_desc: leftover instance(s):$_left" + fi +} + +if [ ! -d "$INSTANCES" ]; then + log "SKIP: tracefs not mounted at $TRACEFS" + exit 0 +fi + +# --------------------------------------------------------------------------- +# 1. SIGINT during a long run +# --------------------------------------------------------------------------- +cleanup_all +$RTLA osnoise top -q -d 30s -P F:1 >/dev/null 2>&1 & +pid=$! +wait_present "$INSTANCES/osnoise_top" 10000 +sleep 5 + +if [ ! -d "$INSTANCES/osnoise_top" ]; then + fail "SIGINT: instance was never created (rtla did not start?)" +else + pass "SIGINT: instance created while running" + kill -INT "$pid" 2>/dev/null + wait "$pid" 2>/dev/null + if wait_gone "$INSTANCES/osnoise_top"; then + pass "SIGINT: instance removed after interrupt" + else + fail "SIGINT: instance still present after interrupt" + fi +fi + +# --------------------------------------------------------------------------- +# 2. SIGTERM during a long run +# +# KNOWN ISSUE (not a test bug): rtla only installs a handler for SIGINT and +# SIGALRM (src/common.c:set_signals). SIGTERM therefore kills rtla outright, +# leaving the tracefs instance behind. +# +# Record it with TAP "not ok ... # TODO" rather than turning it into a pass: +# a TODO is still visible in the log, keeps the suite green, and +# - unlike "pass" - it does not hide a real cleanup regression if the +# SIGTERM path ever changes. Remove the TODO directive once rtla handles +# SIGTERM. +# --------------------------------------------------------------------------- +KNOWN_SIGTERM_LEAK=1 +cleanup_all +$RTLA osnoise top -q -d 30s -P F:1 >/dev/null 2>&1 & +pid=$! +if ! wait_present "$INSTANCES/osnoise_top" 10000; then + fail "SIGTERM: instance was never created (rtla did not start)" + kill -TERM "$pid" 2>/dev/null + wait "$pid" 2>/dev/null +else +sleep 1 + +if ! kill -0 "$pid" 2>/dev/null; then + fail "SIGTERM: rtla died before the signal was sent" +else + kill -TERM "$pid" 2>/dev/null + wait "$pid" 2>/dev/null + if wait_gone "$INSTANCES/osnoise_top"; then + pass "SIGTERM: instance removed after terminate" + elif [ "$KNOWN_SIGTERM_LEAK" -eq 1 ]; then + todo "SIGTERM: instance leaked (rtla has no SIGTERM handler)" + else + fail "SIGTERM: instance still present after terminate" + fi +fi +fi + +# --------------------------------------------------------------------------- +# 3. rtla's own -d timeout path +# --------------------------------------------------------------------------- +cleanup_all +$RTLA osnoise top -q -d 2s -P F:1 >/dev/null 2>&1 +rc=$? +if wait_gone "$INSTANCES/osnoise_top"; then + pass "self-timeout: instance removed (exit=$rc)" +else + fail "self-timeout: instance still present (exit=$rc)" +fi + +# --------------------------------------------------------------------------- +# 4. shell action failure (-a / --on-threshold shell,command=...) +# --------------------------------------------------------------------------- +cleanup_all +$RTLA osnoise top -q -d 5s -P F:1 -r 1000 -S 1 \ + --on-threshold 'shell,command="/bin/false"' >/dev/null 2>&1 +rc=$? +if wait_gone "$INSTANCES/osnoise_top"; then + pass "action-failure: instance removed (exit=$rc)" +else + fail "action-failure: instance still present (exit=$rc)" +fi + +# --------------------------------------------------------------------------- +# 5. repeated interrupted runs must not poison the next run +# --------------------------------------------------------------------------- +cleanup_all +for n in 1 2 3; do + $RTLA osnoise top -q -d 20s -P F:1 >/dev/null 2>&1 & + pid=$! + sleep 1 + kill -INT "$pid" 2>/dev/null + wait "$pid" 2>/dev/null +done + +$RTLA osnoise top -q -d 2s -P F:1 >/dev/null 2>&1 +rc=$? +if [ "$rc" -eq 0 ]; then + pass "repeated interrupts: following run still succeeds" +else + fail "repeated interrupts: following run failed (exit=$rc)" +fi +if wait_gone "$INSTANCES/osnoise_top"; then + pass "repeated interrupts: no leftover instance" +else + fail "repeated interrupts: leftover instance" +fi + +cleanup_all +log "" +log "SUMMARY: $PASS passed, $FAIL failed, $TODO_N known issues" +[ "$FAIL" -eq 0 ] base-commit: 2f2f7eeef8b0a1a9b9ca998231419873ccae8d4e -- 2.43.0