1#!/bin/sh 2 3# 4# SPDX-License-Identifier: BSD-2-Clause 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# procctl(2) threaded test 31 32# panic: exiting process is stopped" seen: 33# https://people.freebsd.org/~pho/stress/log/log0285.txt 34 35prog=`basename ${0%.sh}` 36cat > /tmp/$prog.c <<EOF 37#include <sys/param.h> 38#include <sys/mman.h> 39#include <sys/procctl.h> 40 41#include <err.h> 42#include <pthread.h> 43#include <stdio.h> 44#include <stdlib.h> 45#include <time.h> 46#include <unistd.h> 47 48static volatile u_int *share; 49 50#define PARALLEL 25 51#define RUNTIME 120 52 53static void * 54tr(void *arg __unused) 55{ 56 for (;;) 57 pause(); 58 59 return (NULL); 60} 61 62static void 63test(void) { 64 pthread_t thr; 65 struct procctl_reaper_kill killemall; 66 pid_t pid; 67 time_t start; 68 int data[20], debug, e, n, m; 69 70 debug = 0; /* set to 1 for debug output */ 71 n = m = 0; 72 if (procctl(P_PID, getpid(), PROC_REAP_ACQUIRE, NULL) == -1) 73 err(EXIT_FAILURE, "Fail to acquire the reaper"); 74 start = time(NULL); 75 while (time(NULL) - start < RUNTIME) { 76 m++; 77 share[0] = 0; 78 if ((pid = fork()) == 0) { 79 e = pthread_create(&thr, NULL, tr, NULL); 80 if (e != 0) 81 errc(1, e, "pthread_create"); 82 share[0] = 1; 83 setproctitle("child"); 84 usleep(arc4random() % 200); 85 _exit(0); 86 } 87 arc4random_buf(data, sizeof(data)); 88 while (share[0] == 0) 89 usleep(10); 90 killemall.rk_sig = SIGTERM; 91 killemall.rk_flags = 0; 92 if (procctl(P_PID, getpid(), PROC_REAP_KILL, 93 &killemall) == 0) 94 n++; 95 if (waitpid(pid, NULL, 0) != pid) 96 err(1, "waitpid()"); 97 } 98 if (debug == 1) 99 fprintf(stderr, "n = %d out of %d\n", n, m); 100 _exit(0); 101} 102 103int 104main(void) { 105 pid_t pids[PARALLEL]; 106 size_t len; 107 int i; 108 109 len = PAGE_SIZE; 110 if ((share = mmap(NULL, len, PROT_READ | PROT_WRITE, 111 MAP_ANON | MAP_SHARED, -1, 0)) == MAP_FAILED) 112 err(1, "mmap"); 113 for (i = 0; i < PARALLEL; i++) { 114 if ((pids[i] = fork()) == 0) 115 test(); 116 } 117 for (i = 0; i < PARALLEL; i++) 118 if (waitpid(pids[i], NULL, 0) != pids[i]) 119 err(1, "waitpid()"); 120} 121EOF 122cc -o /tmp/$prog -Wall -Wextra -O0 /tmp/$prog.c -lpthread || exit 1 123rm /tmp/$prog.c 124 125here=`pwd` 126cd /tmp 127./$prog; s=$? 128cd $here 129 130rm /tmp/$prog 131exit $s 132