From 048714d9df73a724d3f84b587f1110963e32f9b3 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Thu, 12 Feb 2026 20:35:19 +0000 Subject: [PATCH] tools/sched_ext: scx_userland: fix restart and stats thread lifecycle bugs Fix three issues in scx_userland's restart path: - exit_req is not reset on restart, causing sched_main_loop() to exit immediately without doing any scheduling work. - stats_printer thread handle is local to spawn_stats_thread(), making it impossible to join from main(). Promote it to file scope. - The stats thread continues reading skel->bss after the skeleton is destroyed on restart, causing a use-after-free. Join the stats thread before destroying the skeleton to ensure it has exited. Signed-off-by: David Carlier Signed-off-by: Tejun Heo --- tools/sched_ext/scx_userland.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/sched_ext/scx_userland.c b/tools/sched_ext/scx_userland.c index 10b31020f44f..63f89b35d999 100644 --- a/tools/sched_ext/scx_userland.c +++ b/tools/sched_ext/scx_userland.c @@ -54,6 +54,7 @@ static bool verbose; static volatile int exit_req; static int enqueued_fd, dispatched_fd; +static pthread_t stats_printer; static struct scx_userland *skel; static struct bpf_link *ops_link; @@ -319,8 +320,6 @@ static void *run_stats_printer(void *arg) static int spawn_stats_thread(void) { - pthread_t stats_printer; - return pthread_create(&stats_printer, NULL, run_stats_printer, NULL); } @@ -375,6 +374,7 @@ static void pre_bootstrap(int argc, char **argv) static void bootstrap(char *comm) { + exit_req = 0; skel = SCX_OPS_OPEN(userland_ops, scx_userland); skel->rodata->num_possible_cpus = libbpf_num_possible_cpus(); @@ -428,6 +428,7 @@ restart: exit_req = 1; bpf_link__destroy(ops_link); + pthread_join(stats_printer, NULL); ecode = UEI_REPORT(skel, uei); scx_userland__destroy(skel); -- 2.30.2