114b7815fSDavid Xu /* $FreeBSD$ */ 214b7815fSDavid Xu #include <signal.h> 314b7815fSDavid Xu #include <stdio.h> 414b7815fSDavid Xu #include <err.h> 514b7815fSDavid Xu #include <errno.h> 614b7815fSDavid Xu #include <sys/types.h> 714b7815fSDavid Xu #include <sys/wait.h> 814b7815fSDavid Xu 914b7815fSDavid Xu int stop_received; 1014b7815fSDavid Xu int exit_received; 1114b7815fSDavid Xu int cont_received; 1214b7815fSDavid Xu 1314b7815fSDavid Xu void job_handler(int sig, siginfo_t *si, void *ctx) 1414b7815fSDavid Xu { 1514b7815fSDavid Xu int status; 1614b7815fSDavid Xu int ret; 1714b7815fSDavid Xu 1814b7815fSDavid Xu if (si->si_code == CLD_STOPPED) { 1914b7815fSDavid Xu stop_received = 1; 2014b7815fSDavid Xu kill(si->si_pid, SIGCONT); 2114b7815fSDavid Xu } else if (si->si_code == CLD_EXITED) { 2214b7815fSDavid Xu ret = waitpid(si->si_pid, &status, 0); 2314b7815fSDavid Xu if (ret == -1) 2414b7815fSDavid Xu errx(1, "waitpid"); 2514b7815fSDavid Xu if (!WIFEXITED(status)) 2614b7815fSDavid Xu errx(1, "!WIFEXITED(status)"); 2714b7815fSDavid Xu exit_received = 1; 2814b7815fSDavid Xu } else if (si->si_code == CLD_CONTINUED) { 2914b7815fSDavid Xu cont_received = 1; 3014b7815fSDavid Xu } 3114b7815fSDavid Xu } 3214b7815fSDavid Xu 3314b7815fSDavid Xu void job_control_test() 3414b7815fSDavid Xu { 3514b7815fSDavid Xu struct sigaction sa; 3614b7815fSDavid Xu pid_t pid; 3714b7815fSDavid Xu int count = 10; 3814b7815fSDavid Xu 3914b7815fSDavid Xu sigemptyset(&sa.sa_mask); 4014b7815fSDavid Xu sa.sa_flags = SA_SIGINFO; 4114b7815fSDavid Xu sa.sa_sigaction = job_handler; 4214b7815fSDavid Xu sigaction(SIGCHLD, &sa, NULL); 4314b7815fSDavid Xu stop_received = 0; 4414b7815fSDavid Xu cont_received = 0; 4514b7815fSDavid Xu exit_received = 0; 4614b7815fSDavid Xu pid = fork(); 4714b7815fSDavid Xu if (pid == 0) { 4814b7815fSDavid Xu kill(getpid(), SIGSTOP); 4914b7815fSDavid Xu exit(1); 5014b7815fSDavid Xu } 5114b7815fSDavid Xu 5214b7815fSDavid Xu while (!(cont_received && stop_received && exit_received)) { 5314b7815fSDavid Xu sleep(1); 5414b7815fSDavid Xu if (--count == 0) 5514b7815fSDavid Xu break; 5614b7815fSDavid Xu } 5714b7815fSDavid Xu if (!(cont_received && stop_received && exit_received)) 5814b7815fSDavid Xu errx(1, "job signals lost"); 5914b7815fSDavid Xu 6014b7815fSDavid Xu printf("job control test OK.\n"); 6114b7815fSDavid Xu } 6214b7815fSDavid Xu 6314b7815fSDavid Xu void rtsig_handler(int sig, siginfo_t *si, void *ctx) 6414b7815fSDavid Xu { 6514b7815fSDavid Xu } 6614b7815fSDavid Xu 6714b7815fSDavid Xu int main() 6814b7815fSDavid Xu { 6914b7815fSDavid Xu struct sigaction sa; 7014b7815fSDavid Xu sigset_t set; 7114b7815fSDavid Xu union sigval val; 7214b7815fSDavid Xu 7314b7815fSDavid Xu /* test job control with empty signal queue */ 7414b7815fSDavid Xu job_control_test(); 7514b7815fSDavid Xu 7614b7815fSDavid Xu /* now full fill signal queue in kernel */ 7714b7815fSDavid Xu sigemptyset(&sa.sa_mask); 7814b7815fSDavid Xu sa.sa_flags = SA_SIGINFO; 7914b7815fSDavid Xu sa.sa_sigaction = rtsig_handler; 8014b7815fSDavid Xu sigaction(SIGRTMIN, &sa, NULL); 8114b7815fSDavid Xu sigemptyset(&set); 8214b7815fSDavid Xu sigaddset(&set, SIGRTMIN); 8314b7815fSDavid Xu sigprocmask(SIG_BLOCK, &set, NULL); 8414b7815fSDavid Xu val.sival_int = 1; 8514b7815fSDavid Xu while (sigqueue(getpid(), SIGRTMIN, val)) 8614b7815fSDavid Xu ; 8714b7815fSDavid Xu 8814b7815fSDavid Xu /* signal queue is fully filled, test the job control again. */ 8914b7815fSDavid Xu job_control_test(); 9014b7815fSDavid Xu return (0); 9114b7815fSDavid Xu } 92