From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-dy1-f169.google.com (mail-dy1-f169.google.com [74.125.82.169]) (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 79CB3429803 for ; Sat, 17 Oct 2026 12:24:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.169 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792239850; cv=none; b=GrOynRKgtrSX80Q574OuEAwRupZWQEr2oe/lAxolCT7Uh8piK9yeZm3crQphnNdzQ+PfTwdbtLTWXT8ZZh/ddBrNcfIlw9nQVvtcDlnVy1hH5Bbw+tpEWL6JdbsQMM6sIvyB7/gWFwHTEOBEFdXTthugoX5KI1YVVqmduTQu6lI= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792239850; c=relaxed/simple; bh=Mx1XA5NXVS41t1VlcXaf7+JjFJSkrUsfufwSRgTXzFk=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=CoyQs0Rkq75qqx6ktUnmMibaGNBJZPX3QHzQCUBbzBWhtELJWathRwnJQRn1y8AlTOXLOV34YhowYZuJ3tbylEkbsgs8U9LxMM9uYkGVOmDvSEYeGvH73KVzHjPWk0C8qK1o/jipeHJEmcMrJOe3pWuAVlBojKVQd/fwU4mW2GE= 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.169 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-f169.google.com with SMTP id 5a478bee46e88-35cd4e8bdbdso1774513eec.1 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=UmrKeTqQfoSGcy/BDwZ8vPeu0m3O/8biSjAZeUP8EfBt23MclFOXlhCA/7aeBKRkZI Ndtv+9IkTuU6wG/Zbng6JkgLpXuDJYMhPy5KJ8xtUfKKB0W6cEW7+eZAKt2ZvqyX3asF iUtxJiyKyn5szJAf4Pg5lh1Ln2/33rZzfXZUv74nPd1PM/WQep/JG8KbzBP0THy/AvQl 7YFlXZsfe5r1isZ+K/1GpctiCaLrnCASa4Z122F2iH3fp2dqCW6kDCyJLMIuR4f8Kfrq oYCEKetzCwC+i1XvDmbjPEGLS2Ip6LVtcuvS4hm7e/LzbON5yHGMoulZBYLgSC8dKr4N OzQA== X-Forwarded-Encrypted: i=1; AKwUvByCk7+mNDhAvVtSbOJT/TxHLhnSohUsRsFDhqz6X0gWpEDb8aHskYT3XeKpjXNCjob9TyTUB28h78Sfq0E=@vger.kernel.org X-Gm-Message-State: AFq9FYIisg5h2CXZMIOypaoQQisHHX5JDwR7JgvFmBlIYv+CACn+XOiO ureLkFugeNRwaenj0n4fsLXkJ6oVIQhWnAwCK98BbOeU55In/B9C/Uaa1/Fjr4Ct X-Gm-Gg: AYBFou0gYKWAWyQRKKpIRidj9+b++ruNlpHUZz50HsRaGCcGzyuzUhXtAwnAQYKFvsh O400EBxfBhyo2V8k4Dd8bRAoq5Q77+U9h6iVflfRDirdksPMkF94gO61JvrinMavR9ugSGR2trq yUFh/yVodyrwKbMJKEpPQs5V+MPgAhHPfLVTrhw4xpqSpiwL69HE3gmjKwEuAoDOJh025P1kaJF RuOKV2EeKv70jaxqwc9xP2kY/p4uDZYV3loJofYlqy+fpETHj3K6UMHxQw1kAxY15RoR9N+4lGU kFlEc9SwFsc7QUG+7x8NFx8LUBPJlRTzt2wkJxc8iOdB9nX+5SlEa6z+i9Rn5+UZ+uHDyriH9+s Nd6AsumgKlgwoW4JQYJ4pglo37qXVMLQPhte8IQTTkp6FAaafqK89j6kNUyKuF5sulP4LEFoe9e SBX30nVL3593zVluO9fa2AHSYEeSUkxMatRSP+/QjlnaeAdP79D6AlroC/w5ZQ6H1Sc4/KtQPPK f5mD01AKrnxyDLeV/5VRAywlK1b+nhJw0jL6KvK/DdDYTc= 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-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