xref: /freebsd/tools/test/stress2/misc/reaper.sh (revision 78bc019d220e05abb5b12f678f9b4a847019bbcc)
1#!/bin/sh
2
3#
4# SPDX-License-Identifier: BSD-2-Clause-FreeBSD
5#
6# Copyright (c) 2022 Peter Holm <pho@FreeBSD.org>
7#
8# Redistribution and use in source and binary forms, with or without
9# modification, are permitted provided that the following conditions
10# are met:
11# 1. Redistributions of source code must retain the above copyright
12#    notice, this list of conditions and the following disclaimer.
13# 2. Redistributions in binary form must reproduce the above copyright
14#    notice, this list of conditions and the following disclaimer in the
15#    documentation and/or other materials provided with the distribution.
16#
17# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27# SUCH DAMAGE.
28#
29
30# Demonstrate lingering child process after a timeout(1) timeout
31# Test scenario suggestions by kib
32
33# Fixed by: 709783373e57 - main - Fix another race between fork(2) and
34# PROC_REAP_KILL subtree
35
36eval prog=reaper.$$
37cat > /tmp/$prog.c <<EOF
38#include <sys/wait.h>
39#include <err.h>
40#include <signal.h>
41#include <stdlib.h>
42#include <unistd.h>
43
44#define MAXP 10000
45
46int
47main(void)
48{
49	pid_t pids[MAXP];
50	int i, parallel;
51	char *cmdline[] = { "SLP", "86400", NULL };
52
53	for (;;) {
54		parallel = arc4random() % MAXP + 1;
55		for (i = 0; i < parallel; i++) {
56			if ((pids[i] = fork()) == 0) {
57				setproctitle("child");
58				if ((arc4random() % 100) < 10) {
59					if (execve(cmdline[0], cmdline,
60					    NULL) == -1)
61				                err(1, "execve");
62				} else {
63					for (;;)
64						pause();
65				}
66				_exit(0); /* never reached */
67			}
68			if (pids[i] == -1)
69				err(1, "fork()");
70		}
71
72		usleep(arc4random() % 500);
73
74		for (i = 0; i < parallel; i++) {
75			if (kill(pids[i], SIGINT) == -1)
76				err(1, "kill(%d)", pids[i]);
77			if (waitpid(pids[i], NULL, 0) != pids[i])
78				err(1, "waitpid(%d)", pids[i]);
79		}
80	}
81}
82EOF
83sed -i '' "s#SLP#/tmp/$prog.sleep#" /tmp/$prog.c
84cc -o /tmp/$prog -Wall -Wextra -O0 /tmp/$prog.c || exit 1
85rm /tmp/$prog.c
86
87cp /bin/sleep /tmp/$prog.sleep
88n=1
89start=`date +%s`
90while true; do
91	timeout 2s /tmp/$prog
92	for i in `jot 50`; do
93		pgrep -q $prog || break
94		sleep .5
95	done
96	if pgrep -q $prog; then
97		e=$((`date +%s` - start))
98		echo "Failed in loop #$n after $e seconds."
99		pgrep "$prog|timeout" | xargs ps -lp
100		pkill $prog
101		rm -f /tmp/$prog /tmp/$prog.sleep
102		exit 1
103	fi
104	[ $((`date +%s` - start)) -ge 600 ] && break
105	n=$((n + 1))
106done
107rm /tmp/$prog /tmp/$prog.sleep
108exit 0
109