1152186Sdavidxu/* $FreeBSD$ */ 2197965Skib#include <sys/types.h> 3197965Skib#include <sys/wait.h> 4197965Skib#include <err.h> 5197965Skib#include <errno.h> 6152186Sdavidxu#include <signal.h> 7152186Sdavidxu#include <stdio.h> 8197965Skib#include <stdlib.h> 9197965Skib#include <unistd.h> 10152186Sdavidxu 11152186Sdavidxuint stop_received; 12152186Sdavidxuint exit_received; 13152186Sdavidxuint cont_received; 14152186Sdavidxu 15197965Skibvoid 16197965Skibjob_handler(int sig, siginfo_t *si, void *ctx) 17152186Sdavidxu{ 18152186Sdavidxu int status; 19152186Sdavidxu int ret; 20152186Sdavidxu 21152186Sdavidxu if (si->si_code == CLD_STOPPED) { 22197965Skib printf("%d: stop received\n", si->si_pid); 23152186Sdavidxu stop_received = 1; 24152186Sdavidxu kill(si->si_pid, SIGCONT); 25152186Sdavidxu } else if (si->si_code == CLD_EXITED) { 26197965Skib printf("%d: exit received\n", si->si_pid); 27152186Sdavidxu ret = waitpid(si->si_pid, &status, 0); 28152186Sdavidxu if (ret == -1) 29152186Sdavidxu errx(1, "waitpid"); 30152186Sdavidxu if (!WIFEXITED(status)) 31152186Sdavidxu errx(1, "!WIFEXITED(status)"); 32152186Sdavidxu exit_received = 1; 33152186Sdavidxu } else if (si->si_code == CLD_CONTINUED) { 34197965Skib printf("%d: cont received\n", si->si_pid); 35152186Sdavidxu cont_received = 1; 36152186Sdavidxu } 37152186Sdavidxu} 38152186Sdavidxu 39197965Skibvoid 40197965Skibjob_control_test(void) 41152186Sdavidxu{ 42152186Sdavidxu struct sigaction sa; 43152186Sdavidxu pid_t pid; 44152186Sdavidxu int count = 10; 45152186Sdavidxu 46152186Sdavidxu sigemptyset(&sa.sa_mask); 47152186Sdavidxu sa.sa_flags = SA_SIGINFO; 48152186Sdavidxu sa.sa_sigaction = job_handler; 49152186Sdavidxu sigaction(SIGCHLD, &sa, NULL); 50152186Sdavidxu stop_received = 0; 51152186Sdavidxu cont_received = 0; 52152186Sdavidxu exit_received = 0; 53197965Skib fflush(stdout); 54152186Sdavidxu pid = fork(); 55152186Sdavidxu if (pid == 0) { 56197965Skib printf("child %d\n", getpid()); 57152186Sdavidxu kill(getpid(), SIGSTOP); 58197965Skib sleep(2); 59152186Sdavidxu exit(1); 60152186Sdavidxu } 61152186Sdavidxu 62152186Sdavidxu while (!(cont_received && stop_received && exit_received)) { 63152186Sdavidxu sleep(1); 64152186Sdavidxu if (--count == 0) 65152186Sdavidxu break; 66152186Sdavidxu } 67152186Sdavidxu if (!(cont_received && stop_received && exit_received)) 68152186Sdavidxu errx(1, "job signals lost"); 69152186Sdavidxu 70152186Sdavidxu printf("job control test OK.\n"); 71152186Sdavidxu} 72152186Sdavidxu 73197965Skibvoid 74197965Skibrtsig_handler(int sig, siginfo_t *si, void *ctx) 75152186Sdavidxu{ 76152186Sdavidxu} 77152186Sdavidxu 78197965Skibint 79197965Skibmain() 80152186Sdavidxu{ 81152186Sdavidxu struct sigaction sa; 82152186Sdavidxu sigset_t set; 83152186Sdavidxu union sigval val; 84152186Sdavidxu 85152186Sdavidxu /* test job control with empty signal queue */ 86152186Sdavidxu job_control_test(); 87152186Sdavidxu 88152186Sdavidxu /* now full fill signal queue in kernel */ 89152186Sdavidxu sigemptyset(&sa.sa_mask); 90152186Sdavidxu sa.sa_flags = SA_SIGINFO; 91152186Sdavidxu sa.sa_sigaction = rtsig_handler; 92152186Sdavidxu sigaction(SIGRTMIN, &sa, NULL); 93152186Sdavidxu sigemptyset(&set); 94152186Sdavidxu sigaddset(&set, SIGRTMIN); 95152186Sdavidxu sigprocmask(SIG_BLOCK, &set, NULL); 96152186Sdavidxu val.sival_int = 1; 97152186Sdavidxu while (sigqueue(getpid(), SIGRTMIN, val)) 98152186Sdavidxu ; 99152186Sdavidxu 100152186Sdavidxu /* signal queue is fully filled, test the job control again. */ 101152186Sdavidxu job_control_test(); 102152186Sdavidxu return (0); 103152186Sdavidxu} 104