Skip to content

Commit 8bda5b7

Browse files
ameryhungAlexei Starovoitov
authored andcommitted
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 <[email protected]> Signed-off-by: Martin KaFai Lau <[email protected]> Acked-by: Eduard Zingerman <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent 34a25aa commit 8bda5b7

File tree

1 file changed

+22
-17
lines changed

1 file changed

+22
-17
lines changed

tools/testing/selftests/bpf/test_progs.c

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,9 @@ static void stdio_hijack(char **log_buf, size_t *log_cnt)
8888
#endif
8989
}
9090

91-
static void stdio_restore_cleanup(void)
91+
static pthread_mutex_t stdout_lock = PTHREAD_MUTEX_INITIALIZER;
92+
93+
static void stdio_restore(void)
9294
{
9395
#ifdef __GLIBC__
9496
if (verbose() && env.worker_id == -1) {
@@ -98,6 +100,8 @@ static void stdio_restore_cleanup(void)
98100

99101
fflush(stdout);
100102

103+
pthread_mutex_lock(&stdout_lock);
104+
101105
if (env.subtest_state) {
102106
fclose(env.subtest_state->stdout_saved);
103107
env.subtest_state->stdout_saved = NULL;
@@ -106,26 +110,21 @@ static void stdio_restore_cleanup(void)
106110
} else {
107111
fclose(env.test_state->stdout_saved);
108112
env.test_state->stdout_saved = NULL;
113+
stdout = env.stdout_saved;
114+
stderr = env.stderr_saved;
109115
}
116+
117+
pthread_mutex_unlock(&stdout_lock);
110118
#endif
111119
}
112120

113-
static void stdio_restore(void)
121+
static int traffic_monitor_print_fn(const char *format, va_list args)
114122
{
115-
#ifdef __GLIBC__
116-
if (verbose() && env.worker_id == -1) {
117-
/* nothing to do, output to stdout by default */
118-
return;
119-
}
120-
121-
if (stdout == env.stdout_saved)
122-
return;
123-
124-
stdio_restore_cleanup();
123+
pthread_mutex_lock(&stdout_lock);
124+
vfprintf(stdout, format, args);
125+
pthread_mutex_unlock(&stdout_lock);
125126

126-
stdout = env.stdout_saved;
127-
stderr = env.stderr_saved;
128-
#endif
127+
return 0;
129128
}
130129

131130
/* Adapted from perf/util/string.c */
@@ -536,7 +535,8 @@ void test__end_subtest(void)
536535
test_result(subtest_state->error_cnt,
537536
subtest_state->skipped));
538537

539-
stdio_restore_cleanup();
538+
stdio_restore();
539+
540540
env.subtest_state = NULL;
541541
}
542542

@@ -1265,7 +1265,10 @@ void crash_handler(int signum)
12651265

12661266
sz = backtrace(bt, ARRAY_SIZE(bt));
12671267

1268-
stdio_restore();
1268+
fflush(stdout);
1269+
stdout = env.stdout_saved;
1270+
stderr = env.stderr_saved;
1271+
12691272
if (env.test) {
12701273
env.test_state->error_cnt++;
12711274
dump_test_log(env.test, env.test_state, true, false, NULL);
@@ -1957,6 +1960,8 @@ int main(int argc, char **argv)
19571960
libbpf_set_strict_mode(LIBBPF_STRICT_ALL);
19581961
libbpf_set_print(libbpf_print_fn);
19591962

1963+
traffic_monitor_set_print(traffic_monitor_print_fn);
1964+
19601965
srand(time(NULL));
19611966

19621967
env.jit_enabled = is_jit_enabled();

0 commit comments

Comments
 (0)