Tests run in VM might be slow, so that children may exit before bpf programs are loaded. SCX_GE(skel->bss->init_task_cnt, num_pre_forks) would fail in this case. For tests working in any env, use signals to control the lifetime of children beyond bpf prog loading deterministically to get expected results. Signed-off-by: Ze Gao <zegao@xxxxxxxxxxx> --- .../selftests/sched_ext/init_enable_count.c | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/sched_ext/init_enable_count.c b/tools/testing/selftests/sched_ext/init_enable_count.c index 97d45f1e5597..3b2c8ab8464f 100644 --- a/tools/testing/selftests/sched_ext/init_enable_count.c +++ b/tools/testing/selftests/sched_ext/init_enable_count.c @@ -31,6 +31,11 @@ open_load_prog(bool global) return skel; } +/* Signal handler for children */ +void sigusr1_handler(int sig) +{ +} + static enum scx_test_status run_test(bool global) { struct init_enable_count *skel; @@ -39,9 +44,15 @@ static enum scx_test_status run_test(bool global) int ret, i, status; struct sched_param param = {}; pid_t pids[num_pre_forks]; + sigset_t blocked_set; skel = open_load_prog(global); + /* Block SIGUSR1 in parent, children will inherit this*/ + sigemptyset(&blocked_set); + sigaddset(&blocked_set, SIGUSR1); + sigprocmask(SIG_BLOCK, &blocked_set, NULL); + /* * Fork a bunch of children before we attach the scheduler so that we * ensure (at least in practical terms) that there are more tasks that @@ -52,7 +63,13 @@ static enum scx_test_status run_test(bool global) pids[i] = fork(); SCX_FAIL_IF(pids[i] < 0, "Failed to fork child"); if (pids[i] == 0) { - sleep(1); + signal(SIGUSR1, sigusr1_handler); + sigprocmask(SIG_UNBLOCK, &blocked_set, NULL); + /* + * Wait indefinitely for signal, will be interrupted + * by signal handler. + */ + pause(); exit(0); } } @@ -60,6 +77,13 @@ static enum scx_test_status run_test(bool global) link = bpf_map__attach_struct_ops(skel->maps.init_enable_count_ops); SCX_FAIL_IF(!link, "Failed to attach struct_ops"); + /* Give children time to set up handlers */ + sleep(1); + + /* Send SIGUSR1 to all children */ + for (int i = 0; i < num_pre_forks; i++) + kill(pids[i], SIGUSR1); + for (i = 0; i < num_pre_forks; i++) { SCX_FAIL_IF(waitpid(pids[i], &status, 0) != pids[i], "Failed to wait for pre-forked child\n"); @@ -69,6 +93,7 @@ static enum scx_test_status run_test(bool global) } bpf_link__destroy(link); + SCX_EQ(skel->bss->init_task_cnt, skel->bss->exit_task_cnt); SCX_GE(skel->bss->init_task_cnt, num_pre_forks); SCX_GE(skel->bss->exit_task_cnt, num_pre_forks); -- 2.41.1