1#!/bin/sh 2 3# 4# Copyright (c) 2025 Peter Holm <pho@FreeBSD.org> 5# 6# SPDX-License-Identifier: BSD-2-Clause 7# 8 9# A kqueuex(KQUEUE_CPONFORK) test scenario 10 11# Sleeping thread seen in WiP code: 12# https://people.freebsd.org/~pho/stress/log/log0615.txt 13 14. ../default.cfg 15 16[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 17ulimit -k 5000 || { echo FAIL; exit 1; } 18 19odir=`pwd` 20prog=$(basename "$0" .sh) 21 22cd /tmp 23sed '1,/^EOF/d' < $odir/$0 > $prog.c 24mycc -o $prog -Wall -Wextra -O2 -g $prog.c -lpthread || exit 1 25rm -f $prog.c 26cd $odir 27 28mount | grep "on $mntpoint " | grep -q md$mdstart && umount -f $mntpoint 29mdconfig -l | grep -q $mdstart && mdconfig -d -u $mdstart 30 31mdconfig -a -t swap -s 2g -u $mdstart 32newfs $newfs_flags md$mdstart > /dev/null 33mount /dev/md$mdstart $mntpoint 34chmod 777 $mntpoint 35 36su $testuser -c "(cd $mntpoint; /tmp/$prog)" & 37for i in `jot 99`; do 38 sleep 1 39 kill -0 $! 2>/dev/null || break 40done 41pkill $prog 42wait 43umount -f $mntpoint 44 45while mount | grep -q $mntpoint; do 46 umount $mntpoint || sleep 1 47done 48mdconfig -d -u $mdstart 49rm -f /tmp/$prog 50 51exit 0 52EOF 53#include <sys/types.h> 54#include <sys/event.h> 55#include <sys/mman.h> 56#include <sys/wait.h> 57 58#include <err.h> 59#include <errno.h> 60#include <fcntl.h> 61#include <pthread.h> 62#include <sched.h> 63#include <signal.h> 64#include <stdio.h> 65#include <stdlib.h> 66#include <string.h> 67#include <unistd.h> 68 69#define PARALLEL 64 70 71static int fd; 72static char path[80]; 73 74static void * 75spin(void *arg __unused) 76{ 77 int i; 78 79 for (i= 0;; i++) { 80 snprintf(path, sizeof(path), "file.%06d.%d", getpid(), i); 81 fd = open(path, O_CREAT | O_TRUNC | O_RDWR, 0622); 82 if (fd == -1 && errno == ENOTDIR) 83 break; 84 if (fd == -1) 85 err(1, "open(%s)", path); 86 close(fd); 87 fd = 0; 88 unlink(path); 89 } 90 fprintf(stderr, "spin loops: %d\n", i + 1); 91 return (NULL); 92} 93 94static void * 95test(void *arg __unused) 96{ 97 struct kevent ev; 98 struct timespec ts; 99 pid_t pid; 100 int i, kq, n; 101 102 for (i = 0; i < 500000; i++) { 103 if ((kq = kqueuex(KQUEUE_CPONFORK)) < 0) 104 err(1, "kqueueex(KQUEUE_CPONFORK)"); 105 106 n = 0; 107 memset(&ev, 0, sizeof(ev)); 108 EV_SET(&ev, fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR, 109 NOTE_DELETE|NOTE_RENAME|NOTE_EXTEND, 0, 0); 110 n++; 111 112 if ((pid = fork()) == 0) { 113 kevent(kq, &ev, n, NULL, 0, NULL); 114 _exit(0); 115 } 116 if (waitpid(pid, NULL, 0) != pid) 117 err(1, "waitpid(%d)", pid); 118 119 kevent(kq, &ev, n, NULL, 0, NULL); 120 memset(&ev, 0, sizeof(ev)); 121 ts.tv_sec = 0; 122 ts.tv_nsec = 1000000; 123 if ((n = kevent(kq, NULL, 0, &ev, 1, &ts)) == -1) 124 err(1, "kevent()"); 125 126 close(kq); 127 } 128 return (NULL); 129} 130 131int 132main(void) 133{ 134 pthread_t cp[PARALLEL], sp; 135 int e, i; 136 137 if ((e = pthread_create(&sp, NULL, spin, NULL)) != 0) 138 errc(1, e, "pthread_create"); 139 140 for (i = 0; i < PARALLEL; i++) { 141 if ((e = pthread_create(&cp[i], NULL, test, NULL)) != 0) 142 errc(1, e, "pthread_create"); 143 } 144 145 for (i = 0; i < PARALLEL; i++) 146 pthread_join(cp[i], NULL); 147 pthread_join(sp, NULL); 148 149 close(fd); 150 151 return (0); 152} 153