1#!/bin/sh 2 3# 4# SPDX-License-Identifier: BSD-2-Clause-FreeBSD 5# 6# Copyright (c) 2020 corydoras@ridiculousfish.com 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# The test scenario is from: 31# Bug 246385 - SIGCHLD dropped if generated while blocked in sigfastblock 32# https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=246385 33# Fixed by r360940 34 35. ../default.cfg 36 37cat > /tmp/sigfastblock2.c <<EOF 38#include <assert.h> 39#include <fcntl.h> 40#include <limits.h> 41#include <signal.h> 42#include <stdio.h> 43#include <stdlib.h> 44#include <unistd.h> 45#include <string.h> 46 47#include <sys/types.h> 48#include <sys/wait.h> 49#include <sys/time.h> 50 51static int pipes[2]; 52 53static void assert_noerr(int res) 54{ 55 if (res < 0) 56 { 57 fprintf(stderr, "error: %s", strerror(res)); 58 exit(EXIT_FAILURE); 59 } 60} 61 62static void sigchld_handler(int sig) 63{ 64 // Write a byte to the write end of pipes. 65 (void)sig; 66 char c = 0; 67 ssize_t amt = write(pipes[1], &c, 1); 68 if (amt < 0) 69 { 70 perror("write"); 71 exit(EXIT_FAILURE); 72 } 73} 74 75static pid_t spawn_child() 76{ 77 pid_t pid = fork(); 78 assert_noerr(pid); 79 if (pid == 0) 80 { 81 _exit(0); 82 } 83 return pid; 84} 85 86int main(void) 87{ 88 // Install SIGCHLD handler with SA_RESTART. 89 struct sigaction chld_act = {}; 90 sigemptyset(&chld_act.sa_mask); 91 chld_act.sa_handler = &sigchld_handler; 92 chld_act.sa_flags = SA_RESTART; 93 assert_noerr(sigaction(SIGCHLD, &chld_act, NULL)); 94 95 // Make our self-pipes. 96 assert_noerr(pipe(pipes)); 97 98 // Spawn and reap children in a loop. 99 for (;;) 100 { 101 // Spawn a child. 102 pid_t child = spawn_child(); 103 assert(child >= 0 && "Invalid pid"); 104 105 // Wait for the SIGCHLD handler to write to us. 106 for (;;) 107 { 108 char buf[PIPE_BUF]; 109 alarm(5); 110 ssize_t amt = read(pipes[0], buf, sizeof buf); 111 if (amt >= 0) 112 break; 113 alarm(0); 114 } 115 116 // Reap it. 117 int status = 0; 118 int pid_res = waitpid(child, &status, WUNTRACED | WCONTINUED); 119 assert(pid_res == child && "Unexpected pid"); 120 } 121 122 return 0; 123} 124EOF 125mycc -o /tmp/sigfastblock2 -Wall -Wextra /tmp/sigfastblock2.c -lpthread || 126 exit 1 127 128timeout 5m /tmp/sigfastblock2; s=$? 129[ $s -eq 124 ] && s=0 130 131rm -f /tmp/sigfastblock2 /tmp/sigfastblock2.c 132exit $s 133