Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests/bpf: allow send_signal test to timeout

The following invocation:

$ t1=send_signal/send_signal_perf_thread_remote \
t2=send_signal/send_signal_nmi_thread_remote \
./test_progs -t $t1,$t2

Leads to send_signal_nmi_thread_remote to be stuck
on a line 180:

/* wait for result */
err = read(pipe_c2p[0], buf, 1);

In this test case:
- perf event PERF_COUNT_HW_CPU_CYCLES is created for parent process;
- BPF program is attached to perf event, and sends a signal to child
process when event occurs;
- parent program burns some CPU in busy loop and calls read() to get
notification from child that it received a signal.

The perf event is declared with .sample_period = 1.
This forces perf to throttle events, and under some unclear conditions
the event does not always occur while parent is in busy loop.
After parent enters read() system call CPU cycles event won't be
generated for parent anymore. Thus, if perf event had not occurred
already the test is stuck.

This commit updates the parent to wait for notification with a timeout,
doing several iterations of busy loop + read_with_timeout().

Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/r/20241112110906.3045278-4-eddyz87@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Eduard Zingerman and committed by
Alexei Starovoitov
3209139d 03066ed3

+19 -13
+19 -13
tools/testing/selftests/bpf/prog_tests/send_signal.c
··· 3 3 #include <sys/time.h> 4 4 #include <sys/resource.h> 5 5 #include "test_send_signal_kern.skel.h" 6 + #include "io_helpers.h" 6 7 7 8 static int sigusr1_received; 8 9 ··· 25 24 int pipe_c2p[2], pipe_p2c[2]; 26 25 int err = -1, pmu_fd = -1; 27 26 volatile int j = 0; 27 + int retry_count; 28 28 char buf[256]; 29 29 pid_t pid; 30 30 int old_prio; ··· 165 163 /* notify child that bpf program can send_signal now */ 166 164 ASSERT_EQ(write(pipe_p2c[1], buf, 1), 1, "pipe_write"); 167 165 168 - /* For the remote test, the BPF program is triggered from this 169 - * process but the other process/thread is signaled. 170 - */ 171 - if (remote) { 172 - if (!attr) { 173 - for (int i = 0; i < 10; i++) 174 - usleep(1); 175 - } else { 176 - for (int i = 0; i < 100000000; i++) 177 - j /= i + 1; 166 + for (retry_count = 0;;) { 167 + /* For the remote test, the BPF program is triggered from this 168 + * process but the other process/thread is signaled. 169 + */ 170 + if (remote) { 171 + if (!attr) { 172 + for (int i = 0; i < 10; i++) 173 + usleep(1); 174 + } else { 175 + for (int i = 0; i < 100000000; i++) 176 + j /= i + 1; 177 + } 178 178 } 179 + /* wait for result */ 180 + err = read_with_timeout(pipe_c2p[0], buf, 1, 100); 181 + if (err == -EAGAIN && retry_count++ < 10000) 182 + continue; 183 + break; 179 184 } 180 - 181 - /* wait for result */ 182 - err = read(pipe_c2p[0], buf, 1); 183 185 if (!ASSERT_GE(err, 0, "reading pipe")) 184 186 goto disable_pmu; 185 187 if (!ASSERT_GT(err, 0, "reading pipe error: size 0")) {