[PATCH v6 22/26] perf test record+probe_libc_inet_pton: Scope event to PID and make non-exclusive

From: Ian Rogers

Date: Mon Sep 28 2026 - 14:31:45 EST


Scope the uprobe name to the pid, retry adding and deleting it as
concurrent uprobe_events writes can fail with EBUSY, and delete it from
an exit trap. Create the temporary files with mktemp rather than reserving
names with mktemp -u. Remove the exclusive tag.

Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Ian Rogers <irogers@xxxxxxxxxx>
---
.../shell/record+probe_libc_inet_pton.sh | 85 ++++++++++++++-----
1 file changed, 65 insertions(+), 20 deletions(-)

diff --git a/tools/perf/tests/shell/record+probe_libc_inet_pton.sh b/tools/perf/tests/shell/record+probe_libc_inet_pton.sh
index 4c9a308a450d..3a363a99ef41 100755
--- a/tools/perf/tests/shell/record+probe_libc_inet_pton.sh
+++ b/tools/perf/tests/shell/record+probe_libc_inet_pton.sh
@@ -1,5 +1,5 @@
#!/bin/bash
-# probe libc's inet_pton & backtrace it with ping (exclusive)
+# probe libc's inet_pton & backtrace it with ping

# Installs a probe on libc's inet_pton function, that will use uprobes,
# then use 'perf trace' on a ping to localhost asking for just one packet
@@ -19,20 +19,27 @@ nm -Dg $libc 2>/dev/null | grep -F -q inet_pton || exit 254
event_pattern='probe_libc:inet_pton(_[[:digit:]]+)?'

add_libc_inet_pton_event() {
+ local attempts=0
+ while [ $attempts -lt 3 ]; do
+ event_name=$(perf probe -f -x $libc -a "inet_pton_$$=inet_pton" 2>&1 | \
+ awk -v ep="$event_pattern" -v l="$libc" '$0 ~ ep && $0 ~ \
+ ("\\(on inet_pton in " l "\\)") {print $1}' | head -n 1)
+
+ if [ -n "$event_name" ]; then
+ return 0
+ fi
+ attempts=$((attempts + 1))
+ sleep 0.1
+ done

- event_name=$(perf probe -f -x $libc -a inet_pton 2>&1 | \
- awk -v ep="$event_pattern" -v l="$libc" '$0 ~ ep && $0 ~ \
- ("\\(on inet_pton in " l "\\)") {print $1}' | head -n 1)
-
- if [ $? -ne 0 ] || [ -z "$event_name" ] ; then
- printf "FAIL: could not add event\n"
- return 1
- fi
+ printf "FAIL: could not add event\n"
+ return 1
}

trace_libc_inet_pton_backtrace() {

- expected=`mktemp -u /tmp/expected.XXX`
+ # Create the files, as root a reserved /tmp name could be a planted symlink.
+ expected=$(mktemp /tmp/expected.XXX) || return 1

echo "ping[][0-9 \.:]+$event_name: \([[:xdigit:]]+\)" > $expected
echo ".*inet_pton\+0x[[:xdigit:]]+[[:space:]]\($libc|inlined\)$" >> $expected
@@ -48,8 +55,8 @@ trace_libc_inet_pton_backtrace() {
;;
esac

- perf_data=`mktemp -u /tmp/perf.data.XXX`
- perf_script=`mktemp -u /tmp/perf.script.XXX`
+ perf_data=$(mktemp /tmp/perf.data.XXX) || return 1
+ perf_script=$(mktemp /tmp/perf.script.XXX) || return 1

# Check presence of libtraceevent support to run perf record
skip_no_probe_record_support "$event_name/$eventattr/"
@@ -59,9 +66,9 @@ trace_libc_inet_pton_backtrace() {
fi

perf record -e $event_name/$eventattr/ -o $perf_data ping -6 -c 1 ::1 > /dev/null 2>&1
- # check if perf data file got created in above step.
- if [ ! -e $perf_data ]; then
- printf "FAIL: perf record failed to create \"%s\" \n" "$perf_data"
+ # mktemp created the file, so check that perf record wrote to it.
+ if [ ! -s "$perf_data" ]; then
+ printf "FAIL: perf record failed to write \"%s\" \n" "$perf_data"
return 1
fi
perf script -i $perf_data | tac | grep -m1 ^ping -B9 | tac > $perf_script
@@ -95,21 +102,59 @@ trace_libc_inet_pton_backtrace() {
# even if the perf script output does not match.
}

+# The probes added, including any _1, _2... suffix perf probe appended.
+libc_inet_pton_events() {
+ perf probe -l 2>/dev/null | awk '{print $1}' |
+ grep -E "^probe_libc:inet_pton_$$(_[[:digit:]]+)?$"
+}
+
delete_libc_inet_pton_event() {
+ # List rather than use event_name, which a signal may have left unset.
+ # Retry as, like adding, deleting can fail with EBUSY.
+ local attempts=0
+ local probe
+
+ while [ $attempts -lt 3 ]; do
+ for probe in $(libc_inet_pton_events); do
+ perf probe -q -d "$probe"
+ done

- if [ -n "$event_name" ] ; then
- perf probe -q -d $event_name
- fi
+ if [ -z "$(libc_inet_pton_events)" ]; then
+ return 0
+ fi
+
+ attempts=$((attempts + 1))
+ sleep 0.1
+ done
+
+ printf "WARN: could not delete event(s): %s\n" \
+ "$(libc_inet_pton_events | tr '\n' ' ')"
+ return 1
+}
+
+cleanup() {
+ rm -f ${perf_data} ${perf_script} ${expected}
+ delete_libc_inet_pton_event
+
+ trap - EXIT TERM INT
+}
+
+trap_cleanup() {
+ cleanup
+ exit 1
}

# Check for IPv6 interface existence
ip a sh lo | grep -F -q inet6 || exit 2
[ "$(id -u)" = 0 ] || exit 2

+# After the skips, as trap_cleanup exits 1. A pid scoped probe is never reused,
+# so always remove it.
+trap trap_cleanup EXIT TERM INT
+
skip_if_no_perf_probe && \
add_libc_inet_pton_event && \
trace_libc_inet_pton_backtrace
err=$?
-rm -f ${perf_data} ${perf_script} ${expected}
-delete_libc_inet_pton_event
+cleanup
exit $err
--
2.56.0.rc1.315.gc6ed9934b7-goog