mirror of
https://github.com/torvalds/linux.git
synced 2026-05-30 18:13:41 +02:00
selftests/bpf: Fix dangling stdout seen by traffic monitor thread
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 For restoring stdout in crash_handler(), since it does not really care about closing stdout, simlpy flush stdout and restore it to the original one. Then, Fix the issue by consolidating stdio_restore_cleanup() and stdio_restore(), and protecting the use/close/assignment 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. Signed-off-by: Amery Hung <ameryhung@gmail.com> Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org> Acked-by: Eduard Zingerman <eddyz87@gmail.com> Link: https://patch.msgid.link/20250305182057.2802606-3-ameryhung@gmail.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
parent
34a25aabcd
commit
8bda5b787d
|
|
@ -88,27 +88,7 @@ static void stdio_hijack(char **log_buf, size_t *log_cnt)
|
|||
#endif
|
||||
}
|
||||
|
||||
static void stdio_restore_cleanup(void)
|
||||
{
|
||||
#ifdef __GLIBC__
|
||||
if (verbose() && env.worker_id == -1) {
|
||||
/* nothing to do, output to stdout by default */
|
||||
return;
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
|
||||
if (env.subtest_state) {
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
static pthread_mutex_t stdout_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
static void stdio_restore(void)
|
||||
{
|
||||
|
|
@ -118,16 +98,35 @@ static void stdio_restore(void)
|
|||
return;
|
||||
}
|
||||
|
||||
if (stdout == env.stdout_saved)
|
||||
return;
|
||||
fflush(stdout);
|
||||
|
||||
stdio_restore_cleanup();
|
||||
pthread_mutex_lock(&stdout_lock);
|
||||
|
||||
stdout = env.stdout_saved;
|
||||
stderr = env.stderr_saved;
|
||||
if (env.subtest_state) {
|
||||
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;
|
||||
stdout = env.stdout_saved;
|
||||
stderr = env.stderr_saved;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&stdout_lock);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int traffic_monitor_print_fn(const char *format, va_list args)
|
||||
{
|
||||
pthread_mutex_lock(&stdout_lock);
|
||||
vfprintf(stdout, format, args);
|
||||
pthread_mutex_unlock(&stdout_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Adapted from perf/util/string.c */
|
||||
static bool glob_match(const char *str, const char *pat)
|
||||
{
|
||||
|
|
@ -536,7 +535,8 @@ void test__end_subtest(void)
|
|||
test_result(subtest_state->error_cnt,
|
||||
subtest_state->skipped));
|
||||
|
||||
stdio_restore_cleanup();
|
||||
stdio_restore();
|
||||
|
||||
env.subtest_state = NULL;
|
||||
}
|
||||
|
||||
|
|
@ -1265,7 +1265,10 @@ void crash_handler(int signum)
|
|||
|
||||
sz = backtrace(bt, ARRAY_SIZE(bt));
|
||||
|
||||
stdio_restore();
|
||||
fflush(stdout);
|
||||
stdout = env.stdout_saved;
|
||||
stderr = env.stderr_saved;
|
||||
|
||||
if (env.test) {
|
||||
env.test_state->error_cnt++;
|
||||
dump_test_log(env.test, env.test_state, true, false, NULL);
|
||||
|
|
@ -1957,6 +1960,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();
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user