From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pl1-f175.google.com (mail-pl1-f175.google.com [209.85.214.175]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BA6E84DEC05 for ; Sun, 18 Oct 2026 22:05:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.175 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792361104; cv=none; b=D0clZs3PvLkHbb5N3Ms9VJN5foYtzMK6SCLFReK/r7cF0b7R3s+N1CNoVqOrO8D/spoE8SDLReSunLVAFkcCHp50+prDWTP1x+7HrIYWLSw3RJ6pOMpOrSOthpXDqZ5ObSH7bGVFKB5fkEO8XhRKlgr/js3+p3HhullIlR4KWMg= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792361104; c=relaxed/simple; bh=zauIoj7DYdW8cMWaD329FhY6axNzTzIKJHEYCxLohYM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=J+3VFwiRtHJ4osSePQ+cFcRKpmmzQ/YjCKfgPKGJdHO9pE6OYiV60DJHKzqEKaMmrRSZotoVob0pNnf7Fn+ClitWhsihg1nAJJFJL6PM+nEFFUOsL00o3GoZ3E4+7HNZxRciR9Yw1SiIvkWZl7DApHlps6ZQVn2/58V/Y2Bz0iI= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Erl9pUtG; arc=none smtp.client-ip=209.85.214.175 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Erl9pUtG" Received: by mail-pl1-f175.google.com with SMTP id d9443c01a7336-2e812e2b31bso7254705ad.3 for ; Sun, 18 Oct 2026 15:05:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792361102; x=1792965902; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=opmL3UHh7n4QvgHM+DCxITPrZJqwJ9zUZp8DhzIayMY=; b=Erl9pUtG+JFjchQdrPI3imxixQezaW07VnxUEFtvWFAuzkxX9boSS2oJFsNUiJhdcr xmVAdBPhU4cxSEB0X3meh2aOE0XeqpYUyizHLDo299WC0IlMgNPU5WTt/ihK5V2+FUjl X8DfgkyBvXbGdIFQRnilTcrIuo2wMEZhj7BzkVktC1XOtNP/bMdi/GwI0m0f90Uy2DP0 1RcOxztzPVcTBfF60E/Otdd5VkXrhL8HajLt9pt7iSpWaNAwIpyPRdnsWXKvDEA/8KpW abTopu9BMOAiAJ5eJ0Q69Hzowh7Yj06hc4r+fuTYxh62s6Dt7ZIteAeM3MY18wuFxI9k ms9g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792361102; x=1792965902; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=opmL3UHh7n4QvgHM+DCxITPrZJqwJ9zUZp8DhzIayMY=; b=bP0CXt1jGUw6GCnI3/xaXsHlriaJpWh63dDzZfC83hRP6zSCRGsiSpTQ/hcoo/Hg6H 59c6Ut5Jn9fThfLf7STBQG1vGGh/EwsArGbY5/Uetd65umQLRY8BkqqBEgLJ9Sd9rfsv HssbgctLgyObXutsyhIS8w6qSYK7e4IYw4Uqd4bKVb/GevfVW1AliqNmGYcswL4J320B zaip75e1aAS/Gg8mTOjuth/tdVNeRhpczzt45MGE4Xf0tNOegc5Sl9WyTPc8F7AtON9B hXpWunfhRhGAyaGR1z089C+4+iam4G7XXD2WXN0TMtRaWeG9BfpoXWFIFRGZHQpr5jzX 8akA== X-Forwarded-Encrypted: i=1; AKwUvBzyfUWxp+aaQGv2iEzY2e3CAguB+sugm7O8duH3wWaZ5QwddLjPIItAzDet2k1mcimUUxNZvCENcyzcNm8=@vger.kernel.org X-Gm-Message-State: AFq9FYKOGhqotJWybV6Tx4SUqBWRiUWo2pn/+bm+R7w8yRrn5HzZPpjt NpGpnPgU4msNOhRcm5iNegSvbUZ0ciYIGT0A9ksppiAw9QXVGiVbGiow X-Gm-Gg: AYBFou3fMcXbwMRliaa3/V8D4f/CZ6yKh6wS8DTdcBhybXn0rWDwSe/EdAC21to0Ab5 v4vdD8fqgrZQTyOmZvTC2YhTPwJOCdQiyBrN/hTePBZSAJ3HnFK05K09wuSY1EsI5oIIAI9pGrk L4tBcekv7kIk9NMHC1hg9T3pZpI2NFrVjW85AwTi2IuNyNBcAgQ+gqtU4XpNTreFckk2f0N1WA+ gv3cy+sx4rsenqNsvlG47aZNkFLXFM9U6jwW7hPirUOJCKB4JWSiV/TpiSqr9P+9GhdQAC2j9KY ThmWEFERlNttU5OEumVZ/9DTKsnyiCDy7MCupHKasIZhPNAFCX0JHTJOHj9C/Jg/J35BSOCflct NI/s34aLdBqrV278hyECHy++ZXtzk7tpPApDTqmb2XR7gvRnMwGmYD3a5SvSXnnn1xUs4BIZsbj iwzrxqAiojGkUH9PTvTHoK2v9+KpWKzGcuFbfv+zgj3Cs1rDQ9bHCMj4EBKeHUwFw4JO4aJA== X-Received: by 2002:a17:90b:4ac6:b0:39d:efa9:cd1a with SMTP id 98e67ed59e1d1-3acee280e87mr5328078a91.4.1792361101759; Sun, 18 Oct 2026 15:05:01 -0700 (PDT) Received: from [10.1.2.130] ([67.185.120.12]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-3ac945e72c6sm17718271a91.5.2026.10.18.15.05.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 18 Oct 2026 15:05:00 -0700 (PDT) From: Kir Kolyshkin Date: Sun, 18 Oct 2026 15:04:40 -0700 Subject: [PATCH 2/2] selftests/cgroup: test cgroup.kill with an exited thread group leader Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Message-Id: <20261018-cgroup-kill-exited-leader-v1-2-c71ad94c20cc@gmail.com> References: <20261018-cgroup-kill-exited-leader-v1-0-c71ad94c20cc@gmail.com> In-Reply-To: <20261018-cgroup-kill-exited-leader-v1-0-c71ad94c20cc@gmail.com> To: Tejun Heo , Johannes Weiner , =?utf-8?q?Michal_Koutn=C3=BD?= , Serge Hallyn , Shakeel Butt , Roman Gushchin , Christian Brauner , Shuah Khan Cc: "Eric W. Biederman" , Oleg Nesterov , cgroups@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, Kir Kolyshkin X-Mailer: b4 0.14.3 Add two tests for cgroup.kill and a process whose thread group leader has exited while another thread is still running: - test_cgkill_exited_leader kills the cgroup the process is in; - test_cgkill_exited_leader_migrated moves the remaining thread to another cgroup, where the process is not listed in cgroup.procs, and kills that cgroup. Both check that the cgroup is no longer populated afterwards. Signed-off-by: Kir Kolyshkin --- tools/testing/selftests/cgroup/test_kill.c | 158 +++++++++++++++++++++++++++++ 1 file changed, 158 insertions(+) diff --git a/tools/testing/selftests/cgroup/test_kill.c b/tools/testing/selftests/cgroup/test_kill.c index bac1ddd8cb94..756bc7193d4b 100644 --- a/tools/testing/selftests/cgroup/test_kill.c +++ b/tools/testing/selftests/cgroup/test_kill.c @@ -2,10 +2,13 @@ #include #include +#include +#include #include #include #include #include +#include #include #include #include @@ -315,6 +318,159 @@ static int test_cgkill_clone_into_killed(const char *root) return ret; } +static int sleep_forever(void *arg) +{ + for (;;) + pause(); + return 0; +} + +/* + * Start a thread and exit the main thread only, leaving behind a zombie + * thread group leader with a live thread. + */ +static int exit_leader_fn(const char *cgroup, void *arg) +{ + const size_t stack_size = 64 * 1024; + char *stack = malloc(stack_size); + + if (!stack) + return EXIT_FAILURE; + + if (clone(sleep_forever, stack + stack_size, + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | + CLONE_THREAD | CLONE_SYSVSEM, NULL) < 0) + return EXIT_FAILURE; + + syscall(SYS_exit, 0); + return EXIT_FAILURE; +} + +static int wait_for_zombie_leader(pid_t pid) +{ + int i; + + for (i = 0; i < 100; i++) { + if (!proc_read_strstr(pid, false, "stat", ") Z ")) + return 0; + usleep(10000); + } + + return -1; +} + +/* + * Test that cgroup.kill kills a process whose thread group leader has + * already exited while its other threads are still running. + */ +static int test_cgkill_exited_leader(const char *root) +{ + int ret = KSFT_FAIL; + char *cgroup = NULL; + pid_t pid = -ESRCH; + + cgroup = cg_name(root, "cg_test_exited_leader"); + if (!cgroup) + goto cleanup; + + if (cg_create(cgroup)) + goto cleanup; + + pid = cg_run_nowait(cgroup, exit_leader_fn, NULL); + if (pid < 0) + goto cleanup; + + if (wait_for_zombie_leader(pid)) + goto cleanup; + + if (cg_read_strcmp(cgroup, "cgroup.events", "populated 1\n")) + goto cleanup; + + if (cg_write(cgroup, "cgroup.kill", "1")) + goto cleanup; + + if (cg_read_strcmp_wait(cgroup, "cgroup.events", "populated 0\n")) + goto cleanup; + + ret = KSFT_PASS; + +cleanup: + if (pid > 0) { + kill(pid, SIGKILL); + wait_for_pid(pid); + } + if (cgroup) + cg_destroy(cgroup); + free(cgroup); + return ret; +} + +/* + * Test that cgroup.kill kills the threads of a process that were migrated + * to the cgroup after their thread group leader had exited, and so are + * not listed in its cgroup.procs. + */ +static int test_cgkill_exited_leader_migrated(const char *root) +{ + char *parent = NULL, *src = NULL, *dst = NULL; + int ret = KSFT_FAIL; + pid_t pid = -ESRCH; + + parent = cg_name(root, "cg_test_exited_leader_migrated"); + if (!parent) + goto cleanup; + + src = cg_name(parent, "src"); + if (!src) + goto cleanup; + + dst = cg_name(parent, "dst"); + if (!dst) + goto cleanup; + + if (cg_create(parent) || cg_create(src) || cg_create(dst)) + goto cleanup; + + pid = cg_run_nowait(src, exit_leader_fn, NULL); + if (pid < 0) + goto cleanup; + + if (wait_for_zombie_leader(pid)) + goto cleanup; + + /* The exiting leader stays behind, only the live thread is moved. */ + if (cg_enter(dst, pid)) + goto cleanup; + + if (cg_read_strcmp(dst, "cgroup.events", "populated 1\n") || + cg_read_strcmp(dst, "cgroup.procs", "")) + goto cleanup; + + if (cg_write(dst, "cgroup.kill", "1")) + goto cleanup; + + if (cg_read_strcmp_wait(dst, "cgroup.events", "populated 0\n")) + goto cleanup; + + ret = KSFT_PASS; + +cleanup: + if (pid > 0) { + kill(pid, SIGKILL); + wait_for_pid(pid); + } + if (dst) + cg_destroy(dst); + if (src) + cg_destroy(src); + if (parent) + cg_destroy(parent); + free(dst); + free(src); + free(parent); + return ret; +} + #define T(x) { x, #x } struct cgkill_test { int (*fn)(const char *root); @@ -324,6 +480,8 @@ struct cgkill_test { T(test_cgkill_tree), T(test_cgkill_forkbomb), T(test_cgkill_clone_into_killed), + T(test_cgkill_exited_leader), + T(test_cgkill_exited_leader_migrated), }; #undef T -- 2.55.0