From: "Darrick J. Wong" <djwong@kernel.org>
To: zlang@redhat.com
Cc: dchinner@redhat.com, fstests@vger.kernel.org, linux-xfs@vger.kernel.org
Subject: [PATCH v3.1 14/34] common: fix pkill by running test program in a separate session
Date: Fri, 14 Feb 2025 13:13:07 -0800 [thread overview]
Message-ID: <20250214211307.GF21799@frogsfrogsfrogs> (raw)
In-Reply-To: <173933094569.1758477.13105816499921786298.stgit@frogsfrogsfrogs>
From: Darrick J. Wong <djwong@kernel.org>
Run each test program with a separate session id so that we can tell
pkill to kill all processes of a given name, but only within our own
session id. This /should/ suffice to run multiple fstests on the same
machine without one instance shooting down processes of another
instance.
This fixes a general problem with using "pkill --parent" -- if the
process being targeted is not a direct descendant of the bash script
calling pkill, then pkill will not do anything. The scrub stress tests
make use of multiple background subshells, which is how a ^C in the
parent process fails to result in fsx/fsstress being killed.
This is necessary to fix SOAK_DURATION runtime constraints for all the
scrub stress tests. However, there is a cost -- the test program no
longer runs with the same controlling tty as ./check, which means that
^Z doesn't work and SIGINT/SIGQUIT are set to SIG_IGN. IOWs, if a test
wants to kill its subprocesses, it must use another signal such as
SIGPIPE. Fortunately, bash doesn't whine about children dying due to
fatal signals if the children run in a different session id.
Unfortunately we have to let it run the test as a background process for
bash to handle SIGINT, and SIGSTOP no longer works properly.
This solution is a bit crap, and I have a better solution for it in the
next patch that uses private pid and mount namespaces. Unfortunately,
that solution adds new minimum requirements for running fstests and
removing previously supported configurations abruptly during a bug fix
is not appropriate behavior.
I also explored alternate designs, and this was the least unsatisfying:
a) Setting the process group didn't work because background subshells
are assigned a new group id.
b) Constraining the pkill/pgrep search to a cgroup could work, but it
seems that procps has only recently (~2023) gained the ability to filter
on a cgroup. Furthermore, we'd have to set up a cgroup in which to run
the fstest. The last decade has been rife with user bug reports
complaining about chaos resulting from multiple pieces of software (e.g.
Docker, systemd, etc.) deciding that they own the entire cgroup
structure without having any means to enforce that statement. We should
not wade into that mess.
c) Putting test subprocesses in a systemd sub-scope and telling systemd
to kill the sub-scope could work because ./check can already use it to
ensure that all child processes of a test are killed. However, this is
an *optional* feature, which means that we'd have to require systemd.
d) Constraining the pkill/pgrep search to a particular pid namespace
could work, but we already have tests that set up their own mount
namespaces, which means the constrained pgrep will not find all child
processes of a test. Though this hasn't been born out through testing?
e) Constraining to any other type of namespace (uts, pid, etc) might not
work because those namespaces might not be enabled. However, combining
a private pid and mount namespace to isolate tests from each other seems
to work better than session ids. This is coming in a subsequent patch,
but to avoid breaking older systems, we will use this as an immediately
deprecated fallback.
f) Revert check-parallel and go back to one fstests instance per system.
Zorro already chose not to revert.
So. Change _run_seq to create a the ./$seq process with a new session
id, update _su calls to use the same session as the parent test, update
all the pkill sites to use a wrapper so that we only target processes
created by *this* instance of fstests, and update SIGINT to SIGPIPE.
Cc: <fstests@vger.kernel.org> # v2024.12.08
Fixes: 8973af00ec212f ("fstests: cleanup fsstress process management")
Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
---
v13.1: add tools/Makefile bit per maintainer request
---
check | 40 ++++++++++++++++++++++++++++++++++------
common/fuzzy | 6 +++---
common/rc | 6 ++++--
tools/Makefile | 5 ++++-
tools/run_setsid | 22 ++++++++++++++++++++++
5 files changed, 67 insertions(+), 12 deletions(-)
create mode 100755 tools/run_setsid
diff --git a/check b/check
index 6f68ebd47c75c1..ef8a8c3b31b3e6 100755
--- a/check
+++ b/check
@@ -698,18 +698,46 @@ _adjust_oom_score -500
# systemd doesn't automatically remove transient scopes that fail to terminate
# when systemd tells them to terminate (e.g. programs stuck in D state when
# systemd sends SIGKILL), so we use reset-failed to tear down the scope.
+#
+# Use setsid to run the test program with a separate session id so that we
+# can pkill only the processes started by this test.
_run_seq() {
- local cmd=(bash -c "test -w ${OOM_SCORE_ADJ} && echo 250 > ${OOM_SCORE_ADJ}; exec ./$seq")
+ local res
+ unset CHILDPID
+ unset FSTESTS_ISOL # set by tools/run_seq_*
if [ -n "${HAVE_SYSTEMD_SCOPES}" ]; then
local unit="$(systemd-escape "fs$seq").scope"
systemctl reset-failed "${unit}" &> /dev/null
- systemd-run --quiet --unit "${unit}" --scope "${cmd[@]}"
+ systemd-run --quiet --unit "${unit}" --scope \
+ ./tools/run_setsid "./$seq" &
+ CHILDPID=$!
+ wait
res=$?
+ unset CHILDPID
systemctl stop "${unit}" &> /dev/null
- return "${res}"
else
- "${cmd[@]}"
+ # bash won't run the SIGINT trap handler while there are
+ # foreground children in a separate session, so we must run
+ # the test in the background and wait for it.
+ ./tools/run_setsid "./$seq" &
+ CHILDPID=$!
+ wait
+ res=$?
+ unset CHILDPID
+ fi
+
+ return $res
+}
+
+_kill_seq() {
+ if [ -n "$CHILDPID" ]; then
+ # SIGPIPE will kill all the children (including fsstress)
+ # without bash logging fatal signal termination messages to the
+ # console
+ pkill -PIPE --session "$CHILDPID"
+ wait
+ unset CHILDPID
fi
}
@@ -718,9 +746,9 @@ _prepare_test_list
fstests_start_time="$(date +"%F %T")"
if $OPTIONS_HAVE_SECTIONS; then
- trap "_summary; exit \$status" 0 1 2 3 15
+ trap "_kill_seq; _summary; exit \$status" 0 1 2 3 15
else
- trap "_wrapup; exit \$status" 0 1 2 3 15
+ trap "_kill_seq; _wrapup; exit \$status" 0 1 2 3 15
fi
function run_section()
diff --git a/common/fuzzy b/common/fuzzy
index e3e1838b5fee12..f4cc5e5c848f9f 100644
--- a/common/fuzzy
+++ b/common/fuzzy
@@ -1205,9 +1205,9 @@ _scratch_xfs_stress_scrub_cleanup() {
echo "Killing stressor processes at $(date)" >> $seqres.full
_kill_fsstress
- _pkill -PIPE --parent $$ xfs_io >> $seqres.full 2>&1
- _pkill -PIPE --parent $$ fsx >> $seqres.full 2>&1
- _pkill -PIPE --parent $$ xfs_scrub >> $seqres.full 2>&1
+ _pkill --echo -PIPE xfs_io >> $seqres.full 2>&1
+ _pkill --echo -PIPE fsx >> $seqres.full 2>&1
+ _pkill --echo -PIPE xfs_scrub >> $seqres.full 2>&1
# Tests are not allowed to exit with the scratch fs frozen. If we
# started a fs freeze/thaw background loop, wait for that loop to exit
diff --git a/common/rc b/common/rc
index bc64e080fe1fc1..f2fbe15104d7ba 100644
--- a/common/rc
+++ b/common/rc
@@ -33,7 +33,7 @@ _test_sync()
# Kill only the processes started by this test.
_pkill()
{
- pkill "$@"
+ pkill --session 0 "$@"
}
# Common execution handling for fsstress invocation.
@@ -2732,9 +2732,11 @@ _require_user_exists()
[ "$?" == "0" ] || _notrun "$user user not defined."
}
+# Run all non-root processes in the same session as the root. Believe it or
+# not, passing $SHELL in this manner works both for "su" and "su -c cmd".
_su()
{
- su "$@"
+ su --session-command $SHELL "$@"
}
# check if a user exists and is able to execute commands.
diff --git a/tools/Makefile b/tools/Makefile
index 3ee532a7e563a9..4e42db4ad8b12d 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -6,12 +6,15 @@ TOPDIR = ..
include $(TOPDIR)/include/builddefs
TOOLS_DIR = tools
+helpers=\
+ run_setsid
include $(BUILDRULES)
-default:
+default: $(helpers)
install: default
$(INSTALL) -m 755 -d $(PKG_LIB_DIR)/$(TOOLS_DIR)
+ $(INSTALL) -m 755 $(helpers) $(PKG_LIB_DIR)/$(TOOLS_DIR)
install-dev install-lib:
diff --git a/tools/run_setsid b/tools/run_setsid
new file mode 100755
index 00000000000000..5938f80e689255
--- /dev/null
+++ b/tools/run_setsid
@@ -0,0 +1,22 @@
+#!/bin/bash
+
+# SPDX-License-Identifier: GPL-2.0
+# Copyright (c) 2025 Oracle. All Rights Reserved.
+#
+# Try starting things in a new process session so that test processes have
+# something with which to filter only their own subprocesses.
+
+if [ -n "${FSTESTS_ISOL}" ]; then
+ # Allow the test to become a target of the oom killer
+ oom_knob="/proc/self/oom_score_adj"
+ test -w "${oom_knob}" && echo 250 > "${oom_knob}"
+
+ exec "$@"
+fi
+
+if [ -z "$1" ] || [ "$1" = "--help" ]; then
+ echo "Usage: $0 command [args...]"
+ exit 1
+fi
+
+FSTESTS_ISOL=setsid exec setsid "$0" "$@"
next prev parent reply other threads:[~2025-02-14 21:13 UTC|newest]
Thread overview: 58+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-02-12 3:30 [PATCHSET v3] fstests: random fixes for v2025.02.02 Darrick J. Wong
2025-02-12 3:30 ` [PATCH 01/34] generic/476: fix fsstress process management Darrick J. Wong
2025-02-12 3:31 ` [PATCH 02/34] metadump: make non-local function variables more obvious Darrick J. Wong
2025-02-12 3:31 ` [PATCH 03/34] metadump: fix cleanup for v1 metadump testing Darrick J. Wong
2025-02-12 3:31 ` [PATCH 04/34] generic/019: don't fail if fio crashes while shutting down Darrick J. Wong
2025-02-12 3:31 ` [PATCH 05/34] fuzzy: do not set _FSSTRESS_PID when exercising fsx Darrick J. Wong
2025-02-12 3:32 ` [PATCH 06/34] common/rc: revert recursive unmount in _clear_mount_stack Darrick J. Wong
2025-02-12 3:32 ` [PATCH 07/34] common/dump: don't replace pids arbitrarily Darrick J. Wong
2025-02-12 3:32 ` [PATCH 08/34] common/populate: correct the parent pointer name creation formulae Darrick J. Wong
2025-02-12 3:33 ` [PATCH 09/34] generic/759,760: fix MADV_COLLAPSE detection and inclusion Darrick J. Wong
2025-02-12 18:31 ` Joanne Koong
2025-02-12 3:33 ` [PATCH 10/34] generic/759,760: skip test if we can't set up a hugepage for IO Darrick J. Wong
2025-02-12 18:39 ` Joanne Koong
2025-02-12 3:33 ` [PATCH 11/34] common/rc: create a wrapper for the su command Darrick J. Wong
2025-02-12 3:33 ` [PATCH 12/34] fuzzy: kill subprocesses with SIGPIPE, not SIGINT Darrick J. Wong
2025-02-12 4:45 ` Dave Chinner
2025-02-12 6:05 ` Darrick J. Wong
2025-02-12 6:10 ` Darrick J. Wong
2025-02-12 3:34 ` [PATCH 13/34] common/rc: hoist pkill to a helper function Darrick J. Wong
2025-02-12 3:34 ` [PATCH 14/34] common: fix pkill by running test program in a separate session Darrick J. Wong
2025-02-14 17:34 ` Zorro Lang
2025-02-14 17:56 ` Darrick J. Wong
2025-02-14 20:50 ` Theodore Ts'o
2025-02-14 21:11 ` Darrick J. Wong
2025-02-15 13:34 ` Zorro Lang
2025-02-14 21:12 ` [PATCH 13.99/34] tools: add a Makefile " Darrick J. Wong
2025-02-15 13:16 ` Zorro Lang
2025-02-14 21:13 ` Darrick J. Wong [this message]
2025-02-15 13:22 ` [PATCH v3.1 14/34] common: fix pkill by running test program in a " Zorro Lang
2025-02-15 16:54 ` Darrick J. Wong
2025-02-12 3:34 ` [PATCH 15/34] check: run tests in a private pid/mount namespace Darrick J. Wong
2025-02-14 17:36 ` Zorro Lang
2025-02-14 21:13 ` [PATCH v3.1 " Darrick J. Wong
2025-02-25 11:27 ` Shinichiro Kawasaki
2025-02-25 15:49 ` Darrick J. Wong
2025-02-25 21:29 ` Dave Chinner
2025-02-26 2:13 ` Shinichiro Kawasaki
2025-02-26 2:18 ` Darrick J. Wong
2025-02-12 3:34 ` [PATCH 16/34] check: deprecate using process sessions to isolate test instances Darrick J. Wong
2025-02-12 3:35 ` [PATCH 17/34] common/rc: don't copy fsstress to $TEST_DIR Darrick J. Wong
2025-02-12 3:35 ` [PATCH 18/34] unmount: resume logging of stdout and stderr for filtering Darrick J. Wong
2025-02-12 3:35 ` [PATCH 19/34] mkfs: don't hardcode log size Darrick J. Wong
2025-02-12 3:35 ` [PATCH 20/34] common/rc: return mount_ret in _try_scratch_mount Darrick J. Wong
2025-02-12 3:36 ` [PATCH 21/34] preamble: fix missing _kill_fsstress Darrick J. Wong
2025-02-12 3:36 ` [PATCH 22/34] generic/650: revert SOAK DURATION changes Darrick J. Wong
2025-02-12 3:36 ` [PATCH 23/34] generic/032: fix pinned mount failure Darrick J. Wong
2025-02-12 3:36 ` [PATCH 24/34] fuzzy: stop __stress_scrub_fsx_loop if fsx fails Darrick J. Wong
2025-02-12 3:37 ` [PATCH 25/34] fuzzy: don't use readarray for xfsfind output Darrick J. Wong
2025-02-12 3:37 ` [PATCH 26/34] fuzzy: always stop the scrub fsstress loop on error Darrick J. Wong
2025-02-12 3:37 ` [PATCH 27/34] fuzzy: port fsx and fsstress loop to use --duration Darrick J. Wong
2025-02-12 4:47 ` Dave Chinner
2025-02-12 3:37 ` [PATCH 28/34] fix _require_scratch_duperemove ordering Darrick J. Wong
2025-02-12 3:38 ` [PATCH 29/34] fsstress: fix a memory leak Darrick J. Wong
2025-02-12 3:38 ` [PATCH 30/34] fsx: fix leaked log file pointer Darrick J. Wong
2025-02-12 3:38 ` [PATCH 31/34] misc: don't put nr_cpus into the fsstress -n argument Darrick J. Wong
2025-02-12 3:39 ` [PATCH 32/34] common/config: add $here to FSSTRESS_PROG Darrick J. Wong
2025-02-12 3:39 ` [PATCH 33/34] config: add FSX_PROG variable Darrick J. Wong
2025-02-12 3:39 ` [PATCH 34/34] build: initialize stack variables to zero by default Darrick J. Wong
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250214211307.GF21799@frogsfrogsfrogs \
--to=djwong@kernel.org \
--cc=dchinner@redhat.com \
--cc=fstests@vger.kernel.org \
--cc=linux-xfs@vger.kernel.org \
--cc=zlang@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox