From: Amery Hung <ameryhung@gmail.com>
To: bpf@vger.kernel.org
Cc: daniel@iogearbox.net, andrii@kernel.org,
alexei.starovoitov@gmail.com, martin.lau@kernel.org,
ameryhung@gmail.com, kernel-team@meta.com
Subject: [PATCH bpf-next v4 3/3] selftests/bpf: Fix dangling stdout seen by traffic monitor thread
Date: Tue, 4 Mar 2025 08:36:26 -0800 [thread overview]
Message-ID: <20250304163626.1362031-3-ameryhung@gmail.com> (raw)
In-Reply-To: <20250304163626.1362031-1-ameryhung@gmail.com>
Traffic monitor thread may see dangling stdout as the main thread closes
and reassigns stdout without protection. This happens when the main thread
finishes one subtest and moves to another one in the same netns_new()
scope.
The issue can be reproduced by running test_progs repeatedly with traffic
monitor enabled:
for ((i=1;i<=100;i++)); do
./test_progs -a flow_dissector_skb* -m '*'
done
Fix it by first consolidating stdout assignment into stdio_restore().
stdout will be restored to env.stdout_saved when a test ends or running
in the crash handler and to test_state.stdout_saved otherwise.
Then, protect use/close/reassignment of stdout with a lock. The locking
in the main thread is always performed regradless of whether traffic
monitor is running or not for simplicity. It won't have any side-effect.
stdio_restore() is kept in the crash handler instead of making all print
functions in the crash handler use env.stdout_saved to make it less
error-prone.
Signed-off-by: Amery Hung <ameryhung@gmail.com>
---
tools/testing/selftests/bpf/test_progs.c | 59 ++++++++++++++++--------
1 file changed, 39 insertions(+), 20 deletions(-)
diff --git a/tools/testing/selftests/bpf/test_progs.c b/tools/testing/selftests/bpf/test_progs.c
index ab0f2fed3c58..5b89f6ca5a0a 100644
--- a/tools/testing/selftests/bpf/test_progs.c
+++ b/tools/testing/selftests/bpf/test_progs.c
@@ -88,7 +88,11 @@ static void stdio_hijack(char **log_buf, size_t *log_cnt)
#endif
}
-static void stdio_restore_cleanup(void)
+static pthread_mutex_t stdout_lock = PTHREAD_MUTEX_INITIALIZER;
+
+static bool in_crash_handler(void);
+
+static void stdio_restore(void)
{
#ifdef __GLIBC__
if (verbose() && env.worker_id == -1) {
@@ -98,34 +102,34 @@ static void stdio_restore_cleanup(void)
fflush(stdout);
- if (env.subtest_state) {
+ pthread_mutex_lock(&stdout_lock);
+
+ if (!env.subtest_state || in_crash_handler()) {
+ if (stdout == env.stdout_saved)
+ goto out;
+
+ fclose(env.test_state->stdout_saved);
+ env.test_state->stdout_saved = NULL;
+ stdout = env.stdout_saved;
+ stderr = env.stderr_saved;
+ } else {
fclose(env.subtest_state->stdout_saved);
env.subtest_state->stdout_saved = NULL;
stdout = env.test_state->stdout_saved;
stderr = env.test_state->stdout_saved;
- } else {
- fclose(env.test_state->stdout_saved);
- env.test_state->stdout_saved = NULL;
}
+out:
+ pthread_mutex_unlock(&stdout_lock);
#endif
}
-static void stdio_restore(void)
+static int traffic_monitor_print_fn(const char *format, va_list args)
{
-#ifdef __GLIBC__
- if (verbose() && env.worker_id == -1) {
- /* nothing to do, output to stdout by default */
- return;
- }
-
- if (stdout == env.stdout_saved)
- return;
-
- stdio_restore_cleanup();
+ pthread_mutex_lock(&stdout_lock);
+ vfprintf(stdout, format, args);
+ pthread_mutex_unlock(&stdout_lock);
- stdout = env.stdout_saved;
- stderr = env.stderr_saved;
-#endif
+ return 0;
}
/* Adapted from perf/util/string.c */
@@ -536,7 +540,8 @@ void test__end_subtest(void)
test_result(subtest_state->error_cnt,
subtest_state->skipped));
- stdio_restore_cleanup();
+ stdio_restore();
+
env.subtest_state = NULL;
}
@@ -1276,6 +1281,18 @@ void crash_handler(int signum)
backtrace_symbols_fd(bt, sz, STDERR_FILENO);
}
+static bool in_crash_handler(void)
+{
+ struct sigaction sigact;
+
+ /* sa_handler will be cleared if invoked since crash_handler is
+ * registered with SA_RESETHAND
+ */
+ sigaction(SIGSEGV, NULL, &sigact);
+
+ return sigact.sa_handler != crash_handler;
+}
+
void hexdump(const char *prefix, const void *buf, size_t len)
{
for (int i = 0; i < len; i++) {
@@ -1957,6 +1974,8 @@ int main(int argc, char **argv)
libbpf_set_strict_mode(LIBBPF_STRICT_ALL);
libbpf_set_print(libbpf_print_fn);
+ traffic_monitor_set_print(traffic_monitor_print_fn);
+
srand(time(NULL));
env.jit_enabled = is_jit_enabled();
--
2.47.1
next prev parent reply other threads:[~2025-03-04 16:36 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-03-04 16:36 [PATCH bpf-next v4 1/3] selftests/bpf: Clean up call sites of stdio_restore() Amery Hung
2025-03-04 16:36 ` [PATCH bpf-next v4 2/3] selftests/bpf: Allow assigning traffic monitor print function Amery Hung
2025-03-04 16:36 ` Amery Hung [this message]
2025-03-05 0:12 ` [PATCH bpf-next v4 3/3] selftests/bpf: Fix dangling stdout seen by traffic monitor thread Eduard Zingerman
2025-03-05 16:52 ` Amery Hung
2025-03-05 1:36 ` Martin KaFai Lau
2025-03-05 16:52 ` Amery Hung
2025-03-04 21:48 ` [PATCH bpf-next v4 1/3] selftests/bpf: Clean up call sites of stdio_restore() Eduard Zingerman
2025-03-04 23:39 ` Amery Hung
2025-03-05 0:14 ` Eduard Zingerman
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=20250304163626.1362031-3-ameryhung@gmail.com \
--to=ameryhung@gmail.com \
--cc=alexei.starovoitov@gmail.com \
--cc=andrii@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=kernel-team@meta.com \
--cc=martin.lau@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