public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Ilya Leoshkevich <iii@linux.ibm.com>
To: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org,
	Heiko Carstens <hca@linux.ibm.com>,
	Vasily Gorbik <gor@linux.ibm.com>,
	Alexander Gordeev <agordeev@linux.ibm.com>,
	Ilya Leoshkevich <iii@linux.ibm.com>
Subject: [PATCH 5/5] perf test java symbol: Add PID namespace variant
Date: Wed,  5 Nov 2025 20:10:28 +0100	[thread overview]
Message-ID: <20251105191626.34998-6-iii@linux.ibm.com> (raw)
In-Reply-To: <20251105191626.34998-1-iii@linux.ibm.com>

Add a PID namespace variant of test_java_symbol.sh. Compared to the
existing test, we must jump through two extra hoops here.

First, we need to check whether unshare is there an is usable, which
may not be the case either due to kernel config or permissions.

Second, we need to keep jshell running after perf record exits in order
to reproduce a real issue with this setup. This means we have to attach
perf after starting jshell, use ctl-fifo and ack-fifo, and work around
perf's inability to attach to existing children.

Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
---
 .../tests/shell/test_java_symbol_pidns.sh     | 135 ++++++++++++++++++
 1 file changed, 135 insertions(+)
 create mode 100755 tools/perf/tests/shell/test_java_symbol_pidns.sh

diff --git a/tools/perf/tests/shell/test_java_symbol_pidns.sh b/tools/perf/tests/shell/test_java_symbol_pidns.sh
new file mode 100755
index 0000000000000..afee6d055ad90
--- /dev/null
+++ b/tools/perf/tests/shell/test_java_symbol_pidns.sh
@@ -0,0 +1,135 @@
+#!/bin/bash
+# Test symbol resolution for java running inside a PID namespace
+# SPDX-License-Identifier: GPL-2.0
+
+set -u -o pipefail
+
+# shellcheck source=lib/setup_libjvmti.sh
+. "$(dirname "$0")/lib/setup_libjvmti.sh"
+
+JSHELL=(jshell -s -J"-agentpath:$LIBJVMTI")
+if ! command -v jshell &>/dev/null; then
+	echo "skip: no jshell, install JDK"
+	exit 2
+fi
+
+UNSHARE=(
+	unshare
+	--user --map-user="$(id -u)" --map-group="$(id -g)"
+	--fork --pid --mount-proc
+)
+if ! "${UNSHARE[@]}" true; then
+	echo "skip: unshare not functional"
+	exit 2
+fi
+
+if [ "$#" -eq 0 ]; then
+	# Verify isolation by running the test inside a separate PID namespace.
+	exec "${UNSHARE[@]}" "$0" "$@" stage2
+fi
+if [ "$1" != stage2 ]; then
+	echo "$0 must be started without arguments"
+	exit 1
+fi
+shift
+
+WORKDIR=$(mktemp -d /tmp/__perf_test_java_symbol_pidns.XXXXX)
+trap 'rm -r "$WORKDIR"' EXIT
+
+test() {
+	TEST_ID=jshell-exit-$JSHELL_EXIT
+
+	# Verify that perf inject can deal with JIT dump produced by jshell
+	# running in PID namespace that is different from its own one.
+	# Make sure jshell is still around when perf inject runs, so attach and
+	# detach perf manually.
+	# jshell is a shell script that runs java as a child process, and perf
+	# cannot attach to existing children. Therefore create a stopped
+	# process, which will exec jshell after it's resumed.
+	JSHELL_STDIN=$WORKDIR/jshell-stdin-$TEST_ID
+	JSHELL_STDOUT=$WORKDIR/jshell-stdout-$TEST_ID
+	mkfifo "$JSHELL_STDIN"
+	mkfifo "$JSHELL_STDOUT"
+	exec {JSHELL_STDIN_FD}<>"$JSHELL_STDIN"
+	exec {JSHELL_STDOUT_FD}<>"$JSHELL_STDOUT"
+	JITDUMPDIR="$WORKDIR" bash -c 'kill -STOP "$$" && exec "$0" "$@"' \
+		"${UNSHARE[@]}" "${JSHELL[@]}" \
+		<&"$JSHELL_STDIN_FD" >&"$JSHELL_STDOUT_FD" &
+	JSHELL_PID=$!
+
+	# Start perf record and wait until it attaches to jshell.
+	PERF_CTL=$WORKDIR/perf-ctl-$TEST_ID
+	PERF_ACK=$WORKDIR/perf-ack-$TEST_ID
+	mkfifo "$PERF_CTL"
+	mkfifo "$PERF_ACK"
+	exec {PERF_CTL_FD}<>"$PERF_CTL"
+	exec {PERF_ACK_FD}<>"$PERF_ACK"
+	PERF_DATA=$WORKDIR/perf-$TEST_ID.data
+	perf record --clockid=1 --delay=-1 \
+		--control="fd:$PERF_CTL_FD,$PERF_ACK_FD" \
+		--output="$PERF_DATA" --pid="$JSHELL_PID" &
+	PERF_PID=$!
+	echo "enable" >&"$PERF_CTL_FD"
+	while IFS= read -r LINE <&"$PERF_ACK_FD"; do
+		[ "$LINE" != "ack" ] || break
+	done
+
+	# Spawn jshell and ask it to run some CPU-intensive code.
+	kill -CONT "$JSHELL_PID"
+	cat >&"$JSHELL_STDIN_FD" <<EOF
+int fib(int x) { return x > 1 ? fib(x - 2) + fib(x - 1) : 1; }
+System.out.println(fib(44));
+EOF
+	while IFS= read -r LINE <&"$JSHELL_STDOUT_FD"; do
+		[ "$LINE" != 1134903170 ] || break
+	done
+
+	# Terminate perf record.
+	echo "stop" >"$PERF_CTL"
+	if ! wait "$PERF_PID"; then
+		echo "Fail to record for java program"
+		exit 1
+	fi
+
+	# Terminate jshell before perf inject.
+	if [ "$JSHELL_EXIT" = "early" ]; then
+		echo "/exit" >&"$JSHELL_STDIN_FD"
+		if ! wait "$JSHELL_PID"; then
+			echo "Fail to run java program"
+			exit 1
+		fi
+	fi
+
+	# Inject the JIT data.
+	PERF_INJ_DATA=$WORKDIR/perf-$TEST_ID.data.inj
+	if ! DEBUGINFOD_URLS="" perf inject --input="$PERF_DATA" \
+		--output="$PERF_INJ_DATA" --jit; then
+		echo "Fail to inject samples"
+		exit 1
+	fi
+
+	# Below is an example of the instruction samples reporting:
+	#   8.18%  jshell           jitted-50116-29.so    [.] Interpreter
+	#   0.75%  Thread-1         jitted-83602-1670.so  [.] jdk.internal.jimage.BasicImageReader.getString(int)
+	# Look for them, while avoiding false positives from lines like this:
+	#   0.03%  jshell           libjvm.so             [.] InterpreterRuntime::resolve_get_put(JavaThread*, Bytecodes::Code)
+	if ! perf report --input="$PERF_INJ_DATA" --stdio |
+		grep ' jshell .* jitted-.*\.so .* \(Interpreter$\|jdk\.internal\)' \
+			&>/dev/null; then
+		echo "Fail to find java symbols"
+		exit 1
+	fi
+
+	# Terminate jshell after perf inject.
+	if [ "$JSHELL_EXIT" = "late" ]; then
+		echo "/exit" >&"$JSHELL_STDIN_FD"
+		if ! wait "$JSHELL_PID"; then
+			echo "Fail to run java program"
+			exit 1
+		fi
+	fi
+}
+
+for JSHELL_EXIT in early late; do
+	test
+done
-- 
2.51.1


      parent reply	other threads:[~2025-11-05 19:16 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-11-05 19:10 [PATCH 0/5] perf jitdump: Fix PID namespace detection Ilya Leoshkevich
2025-11-05 19:10 ` [PATCH 1/5] " Ilya Leoshkevich
2025-11-07  2:16   ` Namhyung Kim
2025-11-07  8:19     ` Ilya Leoshkevich
2025-11-14  8:07       ` Namhyung Kim
2025-11-14 12:44         ` Ilya Leoshkevich
2025-11-14 18:44           ` Namhyung Kim
2025-11-05 19:10 ` [PATCH 2/5] perf test java symbol: Get rid of shellcheck warnings Ilya Leoshkevich
2025-11-07  2:07   ` Namhyung Kim
2025-11-07  7:57     ` Ilya Leoshkevich
2025-11-05 19:10 ` [PATCH 3/5] perf test java symbol: Extract LIBJVMTI detection Ilya Leoshkevich
2025-11-05 19:10 ` [PATCH 4/5] perf test java symbol: Fix a false negative in symbol regex Ilya Leoshkevich
2025-11-07  2:08   ` Namhyung Kim
2025-11-07  7:59     ` Ilya Leoshkevich
2025-11-05 19:10 ` Ilya Leoshkevich [this message]

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=20251105191626.34998-6-iii@linux.ibm.com \
    --to=iii@linux.ibm.com \
    --cc=acme@kernel.org \
    --cc=agordeev@linux.ibm.com \
    --cc=gor@linux.ibm.com \
    --cc=hca@linux.ibm.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-perf-users@vger.kernel.org \
    /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