git: 896809e29675 - main - stress2: Added killpg(2) scenarios
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 31 Jul 2023 07:07:58 UTC
The branch main has been updated by pho: URL: https://cgit.FreeBSD.org/src/commit/?id=896809e296752c54884bde3b04cce213938dfa26 commit 896809e296752c54884bde3b04cce213938dfa26 Author: Peter Holm <pho@FreeBSD.org> AuthorDate: 2023-07-31 07:07:06 +0000 Commit: Peter Holm <pho@FreeBSD.org> CommitDate: 2023-07-31 07:07:06 +0000 stress2: Added killpg(2) scenarios --- tools/test/stress2/misc/killpg2.sh | 197 +++++++++++++++++++++++++++++++++++++ tools/test/stress2/misc/killpg3.sh | 192 ++++++++++++++++++++++++++++++++++++ tools/test/stress2/misc/killpg4.sh | 114 +++++++++++++++++++++ 3 files changed, 503 insertions(+) diff --git a/tools/test/stress2/misc/killpg2.sh b/tools/test/stress2/misc/killpg2.sh new file mode 100755 index 000000000000..5e986f059637 --- /dev/null +++ b/tools/test/stress2/misc/killpg2.sh @@ -0,0 +1,197 @@ +#!/bin/sh + +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2023 Peter Holm <pho@FreeBSD.org> +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +# killpg(2) version of reaper.sh. No problems seen. + +. ../default.cfg + +prog=$(basename "$0" .sh) +cat > /tmp/$prog.c <<EOF +#include <sys/param.h> +#include <sys/mman.h> +#include <sys/wait.h> + +#include <err.h> +#include <errno.h> +#include <pwd.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <unistd.h> + +static volatile u_int *share; + +#define CONT 0 +#define GID 1 +#define SYNC 2 +#define MAXP 10000 + +static void +hand(int i __unused) { + _exit(0); +} + +static void +looper(void) +{ + struct sigaction sa; + time_t start; + struct passwd *pw; + pid_t pids[MAXP]; + int i, parallel; + + setproctitle("looper"); + sa.sa_handler = SIG_IGN; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + if (sigaction(SIGUSR1, &sa, NULL) == -1) + err(1, "sigaction"); + + if ((pw = getpwnam("TUSER")) == NULL) + err(1, "no such user: TUSER"); + + if (setgroups(1, &pw->pw_gid) || + setegid(pw->pw_gid) || setgid(pw->pw_gid) || + seteuid(pw->pw_uid) || setuid(pw->pw_uid)) + err(1, "Can't drop privileges to \"TUSER\""); + endpwent(); + setpgrp(0, 0); + share[GID] = getpgrp(); + share[SYNC] = 1; + start = time(NULL); + while (time(NULL) - start < 120) { + parallel = arc4random() % MAXP + 1; + for (i = 0; i < parallel; i++) { + if ((pids[i] = fork()) == 0) { + sa.sa_handler = hand; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + if (sigaction(SIGUSR1, &sa, NULL) == -1) + err(1, "sigaction"); + setproctitle("child"); + for (;;) + pause(); + _exit(0); /* never reached */ + } + if (pids[i] == -1) + err(1, "fork()"); + } + for (i = 0; i < parallel; i++) { + if (waitpid(pids[i], NULL, 0) != pids[i]) + err(1, "waitpid(%d) in looper", pids[i]); + } + } + _exit(0); +} + +static void +killer(void) +{ + int e, gid; + + while (share[SYNC] == 0) + ; + gid = share[GID]; + while (share[CONT] == 1) { + usleep(arc4random() % 50000); + gid = share[GID]; + if (gid != 0) { + e = 0; + while (e == 0) { + if (killpg(gid, SIGUSR1) == -1) { + e = 1; + if (errno != ESRCH) + err(1, "pgkill(%d)", gid); + } + usleep(5000 + arc4random() % 5000); + } + } + } + _exit(0); +} + +int +main(void) +{ + size_t len; + time_t start; + int lpid, kpid, s1, s2; + + len = PAGE_SIZE; + if ((share = mmap(NULL, len, PROT_READ | PROT_WRITE, + MAP_ANON | MAP_SHARED, -1, 0)) == MAP_FAILED) + err(1, "mmap"); + + start = time(NULL); + while (time(NULL) - start < 120) { + share[CONT] = 1; + share[GID] = 0; + share[SYNC] = 0; + if ((lpid = fork()) == 0) + looper(); + usleep(arc4random() % 100000); + if ((kpid = fork()) == 0) + killer(); + + if (waitpid(lpid, &s1, 0) != lpid) + err(1, "waitpid looper"); + usleep(arc4random() % 1000); + share[CONT] = 0; + waitpid(kpid, &s2, 0); + } + + return (0); +} +EOF +sed -i '' "s#TUSER#$testuser#" /tmp/$prog.c +cc -o /tmp/$prog -Wall -Wextra -O0 /tmp/$prog.c || exit 1 +rm /tmp/$prog.c + +n=1 +start=`date +%s` +while true; do + /tmp/$prog + for i in `jot 50`; do + pgrep -q $prog || break + sleep .5 + done + if pgrep -q $prog; then + e=$((`date +%s` - start)) + echo "Failed in loop #$n after $e seconds." + pgrep "$prog|timeout" | xargs ps -jp + pkill $prog + rm -f /tmp/$prog + exit 1 + fi + [ $((`date +%s` - start)) -ge 600 ] && break + n=$((n + 1)) +done +rm /tmp/$prog +exit 0 diff --git a/tools/test/stress2/misc/killpg3.sh b/tools/test/stress2/misc/killpg3.sh new file mode 100755 index 000000000000..304b3e320f2f --- /dev/null +++ b/tools/test/stress2/misc/killpg3.sh @@ -0,0 +1,192 @@ +#!/bin/sh + +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2023 Peter Holm <pho@FreeBSD.org> +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +# killpg(2) version of reaper.sh. No problems seen. + +. ../default.cfg + +prog=$(basename "$0" .sh) +cat > /tmp/$prog.c <<EOF +#include <sys/param.h> +#include <sys/mman.h> +#include <sys/wait.h> + + +#include <err.h> +#include <errno.h> +#include <pwd.h> +#include <signal.h> +#include <stdatomic.h> +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <unistd.h> + +static _Atomic(int) *share; + +#define GID 0 +#define PARALLEL 10 +#define RDY 1 +#define MAXP 7000 + +static void +hand(int i __unused) { + _exit(0); +} + +static void +innerloop(int parallel) +{ + pid_t pids[MAXP]; + struct sigaction sa; + int i; + + usleep(1000); + for (i = 0; i < parallel; i++) { + if ((pids[i] = fork()) == 0) { + sa.sa_handler = hand; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + if (sigaction(SIGUSR1, &sa, NULL) == -1) + err(1, "sigaction"); + atomic_fetch_add(&share[RDY], 1); + setproctitle("child"); + for (;;) + pause(); + _exit(0); /* never reached */ + } + if (pids[i] == -1) + err(1, "fork()"); + } + for (i = 0; i < parallel; i++) { + if (waitpid(pids[i], NULL, 0) != pids[i]) + err(1, "waitpid(%d) in looper", pids[i]); + } + _exit(0); +} + +static void +looper(void) +{ + struct sigaction sa; + struct passwd *pw; + pid_t pids[MAXP]; + int i, parallel; + + setproctitle("looper"); + sa.sa_handler = SIG_IGN; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + if (sigaction(SIGUSR1, &sa, NULL) == -1) + err(1, "sigaction"); + + if ((pw = getpwnam("TUSER")) == NULL) + err(1, "no such user: TUSER"); + + if (setgroups(1, &pw->pw_gid) || + setegid(pw->pw_gid) || setgid(pw->pw_gid) || + seteuid(pw->pw_uid) || setuid(pw->pw_uid)) + err(1, "Can't drop privileges to \"TUSER\""); + endpwent(); + setpgrp(0, 0); + share[GID] = getpgrp(); + parallel = arc4random() % MAXP + 1; + parallel = parallel / PARALLEL * PARALLEL; + for (i = 0; i < PARALLEL; i++) { + if ((pids[i] = fork()) == 0) + innerloop(parallel / PARALLEL); + } + while (atomic_load(&share[RDY]) != parallel) + usleep(10000); + if (killpg(share[GID], SIGUSR1) == -1) + err(1, "pgkill(%d)", share[GID]); + for (i = 0; i < 4; i++) { + if (waitpid(pids[i], NULL, 0) != pids[i]) + err(1, "waitpid(%d) in looper", pids[i]); + } + _exit(0); +} + +int +main(void) +{ + size_t len; + time_t start; + int lpid, s1; + + len = PAGE_SIZE; + if ((share = mmap(NULL, len, PROT_READ | PROT_WRITE, + MAP_ANON | MAP_SHARED, -1, 0)) == MAP_FAILED) + err(1, "mmap"); + + start = time(NULL); + while (time(NULL) - start < 120) { + share[GID] = 0; + share[RDY] = 0; + if ((lpid = fork()) == 0) + looper(); + if (waitpid(lpid, &s1, 0) != lpid) + err(1, "waitpid looper"); + } + + return (0); +} +EOF +sed -i '' "s#TUSER#$testuser#" /tmp/$prog.c +mycc -o /tmp/$prog -Wall -Wextra -O0 /tmp/$prog.c || exit 1 +rm /tmp/$prog.c + +export MAXSWAPPCT=70 +n=1 +start=`date +%s` +while true; do + ../testcases/swap/swap -t 2m -i 20 > /dev/null & + /tmp/$prog & pid=$! + st=`date +%s` + while kill -0 $pid > /dev/null 2>&1; do + e=$((`date +%s` - st)) + if [ $e -ge 120 ]; then + while pgrep -q swap; do pkill swap; done + fi + if [ $e -ge 600 ]; then + echo "Failed in loop #$n after $e seconds." + ps -jU$testuser | head -20 + kill $pid + pkill -U$testuser + wait + rm -f /tmp/$prog + exit 1 + fi + done + wait + [ $((`date +%s` - start)) -ge 300 ] && break + n=$((n + 1)) +done +rm /tmp/$prog +exit 0 diff --git a/tools/test/stress2/misc/killpg4.sh b/tools/test/stress2/misc/killpg4.sh new file mode 100755 index 000000000000..448a7f60dd4b --- /dev/null +++ b/tools/test/stress2/misc/killpg4.sh @@ -0,0 +1,114 @@ +#!/bin/sh + +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2023 Peter Holm <pho@FreeBSD.org> +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +# Another killpg(2) test scenario. No problems seen. + +. ../default.cfg +export prog=$(basename "$0" .sh) +set -u + +cat > /tmp/$prog.c <<EOF +#include <sys/wait.h> +#include <err.h> +#include <time.h> +#include <stdlib.h> +#include <unistd.h> +#define PARALLEL 2 + +int +test(void) +{ + pid_t pid; + time_t start; + + start = time(NULL); + while (time(NULL) - start < 300) { + if ((pid = fork()) == -1) + err(1, "fork()"); + if (pid == 0) { + if (arc4random() % 100 < 20) + usleep(arc4random() % 5000); + _exit(0); /* Not reached */ + } + if (waitpid(pid, NULL, 0) != pid) + err(1, "waitpid()"); + } + _exit(0); +} + +int +main(void) +{ + pid_t pids[PARALLEL]; + int i; + + for (i = 0; i < PARALLEL; i++) { + test(); + } + for (i = 0; i < PARALLEL; i++) { + if (waitpid(pids[i], NULL, 0) != pids[i]) + err(1, "waotpid() main"); + } + +} +EOF +mycc -o /tmp/$prog -Wall -Wextra -O2 /tmp/$prog.c || exit 1 + +export MAXSWAPPCT=80 +../testcases/swap/swap -t 2m -i 5 > /dev/null 2>&1 & +sleep .5 +start=`date +%s` +while [ $((`date +%s` - start)) -lt 120 ]; do + for i in `jot 200 100`; do + ( + sl=$prog.$i + sleep=/tmp/$sl + cp /tmp/$prog $sleep + su $testuser -c "$sleep & $sleep & $sleep &" & pid=$! + for j in `jot 10`; do + pgrep -q "$sl" && break + sleep .5 + done + pgrep -q "$sl" || { echo "No start"; exit 1; } + pgid=`pgrep "$sl" | xargs ps -jp | sed 1d | \ + tail -1 | awk '{print $4}'` + [ -z "$pgid" ] && { echo "Zero pgid:$pgid"; ps aj | \ + sed -n "1p;/$sl/p"; exit 1; } + sleep 1.`jot -r 1 2 9` + kill -- -$pgid || { echo "kill -$pgid failed"; exit 1; } + wait $pid + rm -f $sleep + ) & + done + while [ `ps -U$testuser | wc -l` -gt 1 ] ; do sleep 2; done +done +while pkill swap; do :; done +wait +rm /tmp/$prog /tmp/$prog.c +exit 0