* [LTP] [PATCH v1] Refactor exit_group01 using new API
@ 2023-08-30 15:55 Andrea Cervesato
2023-09-06 9:02 ` Richard Palethorpe
0 siblings, 1 reply; 2+ messages in thread
From: Andrea Cervesato @ 2023-08-30 15:55 UTC (permalink / raw)
To: ltp
From: Andrea Cervesato <andrea.cervesato@suse.com>
We provided a different approach to exit_group() testing, spawning
multiple threads inside the child and checking if they get killed with
the parent process.
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
testcases/kernel/syscalls/exit_group/Makefile | 2 +
.../kernel/syscalls/exit_group/exit_group01.c | 137 +++++++++++-------
2 files changed, 85 insertions(+), 54 deletions(-)
diff --git a/testcases/kernel/syscalls/exit_group/Makefile b/testcases/kernel/syscalls/exit_group/Makefile
index 1273a4e9c..adbac3c51 100644
--- a/testcases/kernel/syscalls/exit_group/Makefile
+++ b/testcases/kernel/syscalls/exit_group/Makefile
@@ -3,6 +3,8 @@
top_srcdir ?= ../../../..
+exit_group01: CFLAGS+=-pthread
+
include $(top_srcdir)/include/mk/testcases.mk
include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/syscalls/exit_group/exit_group01.c b/testcases/kernel/syscalls/exit_group/exit_group01.c
index 5bf5b0218..0ed008115 100644
--- a/testcases/kernel/syscalls/exit_group/exit_group01.c
+++ b/testcases/kernel/syscalls/exit_group/exit_group01.c
@@ -1,68 +1,97 @@
-/******************************************************************************
- * Copyright (c) Crackerjack Project., 2007 *
- * Ported to LTP by Manas Kumar Nayak <maknayak@in.ibm.com> *
- * Copyright (C) 2015 Cyril Hrubis <chrubis@suse.cz> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See *
- * the GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the Free Software Foundation, *
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
- * *
- ******************************************************************************/
-
-#include <stdio.h>
-#include <errno.h>
-#include <linux/unistd.h>
-#include <sys/wait.h>
-
-#include "test.h"
-#include "safe_macros.h"
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) Crackerjack Project., 2007
+ * Ported to LTP by Manas Kumar Nayak <maknayak@in.ibm.com>
+ * Copyright (c) 2015 Linux Test Project
+ * Copyright (C) 2015 Cyril Hrubis <chrubis@suse.cz>
+ * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * [Description]
+ *
+ * This test checks if exit_group() correctly ends a spawned child and all its
+ * running threads.
+ */
+
+#include <stdlib.h>
+#include "tst_safe_pthread.h"
+#include "tst_test.h"
#include "lapi/syscalls.h"
-char *TCID = "exit_group01";
-int testno;
-int TST_TOTAL = 1;
+/* gittid is not defined by glibc */
+#define gettid() syscall(SYS_gettid)
+
+#define THREADS_NUM 10
-static void verify_exit_group(void)
+static pid_t *tids;
+
+static void *worker(void *arg)
{
- pid_t cpid, w;
- int status;
+ int i = *((int *)arg);
- cpid = fork();
- if (cpid == -1)
- tst_brkm(TFAIL | TERRNO, NULL, "fork failed");
+ tids[i] = gettid();
- if (cpid == 0) {
- TEST(tst_syscall(__NR_exit_group, 4));
- } else {
- w = SAFE_WAIT(NULL, &status);
-
- if (WIFEXITED(status) && (WEXITSTATUS(status) == 4)) {
- tst_resm(TPASS, "exit_group() succeeded");
- } else {
- tst_resm(TFAIL | TERRNO,
- "exit_group() failed (wait status = %d)", w);
- }
+ TST_CHECKPOINT_WAKE(0);
+ pause();
+
+ return arg;
+}
+
+static void spawn_threads(void)
+{
+ pthread_t threads[THREADS_NUM];
+
+ for (int i = 0; i < THREADS_NUM; i++) {
+ SAFE_PTHREAD_CREATE(&threads[i], NULL, worker, (void *)&i);
+ TST_CHECKPOINT_WAIT(0);
}
}
-int main(int ac, char **av)
+static void run(void)
{
- int lc;
+ pid_t pid;
+ int status;
- tst_parse_opts(ac, av, NULL, NULL);
+ pid = SAFE_FORK();
+ if (!pid) {
+ spawn_threads();
- for (lc = 0; TEST_LOOPING(lc); lc++)
- verify_exit_group();
+ TEST(tst_syscall(__NR_exit_group, 4));
+ if (TST_RET == -1)
+ tst_brk(TBROK | TERRNO, "exit_group() error");
+
+ return;
+ }
+
+ SAFE_WAITPID(pid, &status, 0);
+
+ TST_EXP_EXPR(WIFEXITED(status) && WEXITSTATUS(status) == 4,
+ "exit_group() succeeded");
+
+ for (int i = 0; i < THREADS_NUM; i++)
+ TST_EXP_FAIL(kill(tids[i], 0), ESRCH);
+}
+
+static void setup(void)
+{
+ tids = SAFE_MMAP(
+ NULL,
+ sizeof(pid_t) * THREADS_NUM,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED | MAP_ANONYMOUS,
+ -1, 0);
+}
- tst_exit();
+static void cleanup(void)
+{
+ SAFE_MUNMAP(tids, sizeof(pid_t) * THREADS_NUM);
}
+
+static struct tst_test test = {
+ .setup = setup,
+ .cleanup = cleanup,
+ .test_all = run,
+ .forks_child = 1,
+ .needs_checkpoints = 1,
+};
--
2.35.3
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [LTP] [PATCH v1] Refactor exit_group01 using new API
2023-08-30 15:55 [LTP] [PATCH v1] Refactor exit_group01 using new API Andrea Cervesato
@ 2023-09-06 9:02 ` Richard Palethorpe
0 siblings, 0 replies; 2+ messages in thread
From: Richard Palethorpe @ 2023-09-06 9:02 UTC (permalink / raw)
To: Andrea Cervesato; +Cc: ltp
Hello,
Andrea Cervesato <andrea.cervesato@suse.de> writes:
> From: Andrea Cervesato <andrea.cervesato@suse.com>
>
> We provided a different approach to exit_group() testing, spawning
> multiple threads inside the child and checking if they get killed with
> the parent process.
>
> Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
> ---
> testcases/kernel/syscalls/exit_group/Makefile | 2 +
> .../kernel/syscalls/exit_group/exit_group01.c | 137 +++++++++++-------
> 2 files changed, 85 insertions(+), 54 deletions(-)
>
> diff --git a/testcases/kernel/syscalls/exit_group/Makefile b/testcases/kernel/syscalls/exit_group/Makefile
> index 1273a4e9c..adbac3c51 100644
> --- a/testcases/kernel/syscalls/exit_group/Makefile
> +++ b/testcases/kernel/syscalls/exit_group/Makefile
> @@ -3,6 +3,8 @@
>
> top_srcdir ?= ../../../..
>
> +exit_group01: CFLAGS+=-pthread
> +
> include $(top_srcdir)/include/mk/testcases.mk
>
> include $(top_srcdir)/include/mk/generic_leaf_target.mk
> diff --git a/testcases/kernel/syscalls/exit_group/exit_group01.c b/testcases/kernel/syscalls/exit_group/exit_group01.c
> index 5bf5b0218..0ed008115 100644
> --- a/testcases/kernel/syscalls/exit_group/exit_group01.c
> +++ b/testcases/kernel/syscalls/exit_group/exit_group01.c
> @@ -1,68 +1,97 @@
> -/******************************************************************************
> - * Copyright (c) Crackerjack Project., 2007 *
> - * Ported to LTP by Manas Kumar Nayak <maknayak@in.ibm.com> *
> - * Copyright (C) 2015 Cyril Hrubis <chrubis@suse.cz> *
> - * *
> - * This program is free software; you can redistribute it and/or modify *
> - * it under the terms of the GNU General Public License as published by *
> - * the Free Software Foundation; either version 2 of the License, or *
> - * (at your option) any later version. *
> - * *
> - * This program is distributed in the hope that it will be useful, *
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of *
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See *
> - * the GNU General Public License for more details. *
> - * *
> - * You should have received a copy of the GNU General Public License *
> - * along with this program; if not, write to the Free Software Foundation, *
> - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
> - * *
> - ******************************************************************************/
> -
> -#include <stdio.h>
> -#include <errno.h>
> -#include <linux/unistd.h>
> -#include <sys/wait.h>
> -
> -#include "test.h"
> -#include "safe_macros.h"
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (c) Crackerjack Project., 2007
> + * Ported to LTP by Manas Kumar Nayak <maknayak@in.ibm.com>
> + * Copyright (c) 2015 Linux Test Project
> + * Copyright (C) 2015 Cyril Hrubis <chrubis@suse.cz>
> + * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
> + */
> +
> +/*\
> + * [Description]
> + *
> + * This test checks if exit_group() correctly ends a spawned child and all its
> + * running threads.
> + */
> +
> +#include <stdlib.h>
> +#include "tst_safe_pthread.h"
> +#include "tst_test.h"
> #include "lapi/syscalls.h"
>
> -char *TCID = "exit_group01";
> -int testno;
> -int TST_TOTAL = 1;
> +/* gittid is not defined by glibc */
> +#define gettid() syscall(SYS_gettid)
> +
> +#define THREADS_NUM 10
>
> -static void verify_exit_group(void)
> +static pid_t *tids;
> +
> +static void *worker(void *arg)
> {
> - pid_t cpid, w;
> - int status;
> + int i = *((int *)arg);
>
> - cpid = fork();
> - if (cpid == -1)
> - tst_brkm(TFAIL | TERRNO, NULL, "fork failed");
> + tids[i] = gettid();
>
> - if (cpid == 0) {
> - TEST(tst_syscall(__NR_exit_group, 4));
> - } else {
> - w = SAFE_WAIT(NULL, &status);
> -
> - if (WIFEXITED(status) && (WEXITSTATUS(status) == 4)) {
> - tst_resm(TPASS, "exit_group() succeeded");
> - } else {
> - tst_resm(TFAIL | TERRNO,
> - "exit_group() failed (wait status = %d)", w);
> - }
> + TST_CHECKPOINT_WAKE(0);
> + pause();
> +
> + return arg;
> +}
> +
> +static void spawn_threads(void)
> +{
> + pthread_t threads[THREADS_NUM];
> +
> + for (int i = 0; i < THREADS_NUM; i++) {
> + SAFE_PTHREAD_CREATE(&threads[i], NULL, worker, (void *)&i);
> + TST_CHECKPOINT_WAIT(0);
> }
> }
>
> -int main(int ac, char **av)
> +static void run(void)
> {
> - int lc;
> + pid_t pid;
> + int status;
>
> - tst_parse_opts(ac, av, NULL, NULL);
> + pid = SAFE_FORK();
> + if (!pid) {
> + spawn_threads();
>
> - for (lc = 0; TEST_LOOPING(lc); lc++)
> - verify_exit_group();
> + TEST(tst_syscall(__NR_exit_group, 4));
> + if (TST_RET == -1)
> + tst_brk(TBROK | TERRNO, "exit_group() error");
> +
> + return;
> + }
> +
> + SAFE_WAITPID(pid, &status, 0);
> +
> + TST_EXP_EXPR(WIFEXITED(status) && WEXITSTATUS(status) == 4,
> + "exit_group() succeeded");
> +
> + for (int i = 0; i < THREADS_NUM; i++)
> + TST_EXP_FAIL(kill(tids[i], 0), ESRCH);
I'm not sure if there is a race condition here because
1. I can't find a synchronisation mechanism when the kernel sends the
kill signal to the children. It just sets the signal then schedules
them.
2. I can't see a clear way that wait{pid,id} would wait for a process
and its children.
In fact I'm not sure if all the children of the thread group leader need
(or can be) to be waited on (you may need __WALL in options).
Could you try waiting on the idividual tids[] and then the pid?
I haven't seen the test fail, but the main test task (sleeping in
waitpid) probably gets scheduled after the child thread tasks. However
this doesn't seem like behaviour we can rely on.
> +}
> +
> +static void setup(void)
> +{
> + tids = SAFE_MMAP(
> + NULL,
> + sizeof(pid_t) * THREADS_NUM,
> + PROT_READ | PROT_WRITE,
> + MAP_SHARED | MAP_ANONYMOUS,
> + -1, 0);
> +}
>
> - tst_exit();
> +static void cleanup(void)
> +{
> + SAFE_MUNMAP(tids, sizeof(pid_t) * THREADS_NUM);
> }
> +
> +static struct tst_test test = {
> + .setup = setup,
> + .cleanup = cleanup,
> + .test_all = run,
> + .forks_child = 1,
> + .needs_checkpoints = 1,
> +};
> --
> 2.35.3
--
Thank you,
Richard.
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2023-09-06 10:38 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-08-30 15:55 [LTP] [PATCH v1] Refactor exit_group01 using new API Andrea Cervesato
2023-09-06 9:02 ` Richard Palethorpe
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox