114b7815fSDavid Xu /* $FreeBSD$ */ 214b7815fSDavid Xu #include <sys/types.h> 314b7815fSDavid Xu #include <sys/wait.h> 4eb9de28fSKonstantin Belousov #include <err.h> 5eb9de28fSKonstantin Belousov #include <errno.h> 6eb9de28fSKonstantin Belousov #include <signal.h> 7eb9de28fSKonstantin Belousov #include <stdio.h> 8eb9de28fSKonstantin Belousov #include <stdlib.h> 9eb9de28fSKonstantin Belousov #include <unistd.h> 1014b7815fSDavid Xu 1114b7815fSDavid Xu int stop_received; 1214b7815fSDavid Xu int exit_received; 1314b7815fSDavid Xu int cont_received; 1414b7815fSDavid Xu 15eb9de28fSKonstantin Belousov void 16eb9de28fSKonstantin Belousov job_handler(int sig, siginfo_t *si, void *ctx) 1714b7815fSDavid Xu { 1814b7815fSDavid Xu int status; 1914b7815fSDavid Xu int ret; 2014b7815fSDavid Xu 2114b7815fSDavid Xu if (si->si_code == CLD_STOPPED) { 22eb9de28fSKonstantin Belousov printf("%d: stop received\n", si->si_pid); 2314b7815fSDavid Xu stop_received = 1; 2414b7815fSDavid Xu kill(si->si_pid, SIGCONT); 2514b7815fSDavid Xu } else if (si->si_code == CLD_EXITED) { 26eb9de28fSKonstantin Belousov printf("%d: exit received\n", si->si_pid); 2714b7815fSDavid Xu ret = waitpid(si->si_pid, &status, 0); 2814b7815fSDavid Xu if (ret == -1) 2914b7815fSDavid Xu errx(1, "waitpid"); 3014b7815fSDavid Xu if (!WIFEXITED(status)) 3114b7815fSDavid Xu errx(1, "!WIFEXITED(status)"); 3214b7815fSDavid Xu exit_received = 1; 3314b7815fSDavid Xu } else if (si->si_code == CLD_CONTINUED) { 34eb9de28fSKonstantin Belousov printf("%d: cont received\n", si->si_pid); 3514b7815fSDavid Xu cont_received = 1; 3614b7815fSDavid Xu } 3714b7815fSDavid Xu } 3814b7815fSDavid Xu 39eb9de28fSKonstantin Belousov void 40eb9de28fSKonstantin Belousov job_control_test(void) 4114b7815fSDavid Xu { 4214b7815fSDavid Xu struct sigaction sa; 4314b7815fSDavid Xu pid_t pid; 4414b7815fSDavid Xu int count = 10; 4514b7815fSDavid Xu 4614b7815fSDavid Xu sigemptyset(&sa.sa_mask); 4714b7815fSDavid Xu sa.sa_flags = SA_SIGINFO; 4814b7815fSDavid Xu sa.sa_sigaction = job_handler; 4914b7815fSDavid Xu sigaction(SIGCHLD, &sa, NULL); 5014b7815fSDavid Xu stop_received = 0; 5114b7815fSDavid Xu cont_received = 0; 5214b7815fSDavid Xu exit_received = 0; 53eb9de28fSKonstantin Belousov fflush(stdout); 5414b7815fSDavid Xu pid = fork(); 5514b7815fSDavid Xu if (pid == 0) { 56eb9de28fSKonstantin Belousov printf("child %d\n", getpid()); 5714b7815fSDavid Xu kill(getpid(), SIGSTOP); 58eb9de28fSKonstantin Belousov sleep(2); 5914b7815fSDavid Xu exit(1); 6014b7815fSDavid Xu } 6114b7815fSDavid Xu 6214b7815fSDavid Xu while (!(cont_received && stop_received && exit_received)) { 6314b7815fSDavid Xu sleep(1); 6414b7815fSDavid Xu if (--count == 0) 6514b7815fSDavid Xu break; 6614b7815fSDavid Xu } 6714b7815fSDavid Xu if (!(cont_received && stop_received && exit_received)) 6814b7815fSDavid Xu errx(1, "job signals lost"); 6914b7815fSDavid Xu 7014b7815fSDavid Xu printf("job control test OK.\n"); 7114b7815fSDavid Xu } 7214b7815fSDavid Xu 73eb9de28fSKonstantin Belousov void 74eb9de28fSKonstantin Belousov rtsig_handler(int sig, siginfo_t *si, void *ctx) 7514b7815fSDavid Xu { 7614b7815fSDavid Xu } 7714b7815fSDavid Xu 78eb9de28fSKonstantin Belousov int 79eb9de28fSKonstantin Belousov main() 8014b7815fSDavid Xu { 8114b7815fSDavid Xu struct sigaction sa; 8214b7815fSDavid Xu sigset_t set; 8314b7815fSDavid Xu union sigval val; 8414b7815fSDavid Xu 8514b7815fSDavid Xu /* test job control with empty signal queue */ 8614b7815fSDavid Xu job_control_test(); 8714b7815fSDavid Xu 8814b7815fSDavid Xu /* now full fill signal queue in kernel */ 8914b7815fSDavid Xu sigemptyset(&sa.sa_mask); 9014b7815fSDavid Xu sa.sa_flags = SA_SIGINFO; 9114b7815fSDavid Xu sa.sa_sigaction = rtsig_handler; 9214b7815fSDavid Xu sigaction(SIGRTMIN, &sa, NULL); 9314b7815fSDavid Xu sigemptyset(&set); 9414b7815fSDavid Xu sigaddset(&set, SIGRTMIN); 9514b7815fSDavid Xu sigprocmask(SIG_BLOCK, &set, NULL); 9614b7815fSDavid Xu val.sival_int = 1; 9714b7815fSDavid Xu while (sigqueue(getpid(), SIGRTMIN, val)) 9814b7815fSDavid Xu ; 9914b7815fSDavid Xu 10014b7815fSDavid Xu /* signal queue is fully filled, test the job control again. */ 10114b7815fSDavid Xu job_control_test(); 10214b7815fSDavid Xu return (0); 10314b7815fSDavid Xu } 104