1 /* $FreeBSD$ */
2 #include <sys/types.h>
3 #include <sys/wait.h>
4 #include <err.h>
5 #include <errno.h>
6 #include <signal.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <unistd.h>
10 
11 int stop_received;
12 int exit_received;
13 int cont_received;
14 
15 void
16 job_handler(int sig, siginfo_t *si, void *ctx)
17 {
18 	int status;
19 	int ret;
20 
21 	if (si->si_code == CLD_STOPPED) {
22 		printf("%d: stop received\n", si->si_pid);
23 		stop_received = 1;
24 		kill(si->si_pid, SIGCONT);
25 	} else if (si->si_code == CLD_EXITED) {
26 		printf("%d: exit received\n", si->si_pid);
27 		ret = waitpid(si->si_pid, &status, 0);
28 		if (ret == -1)
29 			errx(1, "waitpid");
30 		if (!WIFEXITED(status))
31 			errx(1, "!WIFEXITED(status)");
32 		exit_received = 1;
33 	} else if (si->si_code == CLD_CONTINUED) {
34 		printf("%d: cont received\n", si->si_pid);
35 		cont_received = 1;
36 	}
37 }
38 
39 void
40 job_control_test(void)
41 {
42 	struct sigaction sa;
43 	pid_t pid;
44 	int count = 10;
45 
46 	sigemptyset(&sa.sa_mask);
47 	sa.sa_flags = SA_SIGINFO;
48 	sa.sa_sigaction = job_handler;
49 	sigaction(SIGCHLD, &sa, NULL);
50 	stop_received = 0;
51 	cont_received = 0;
52 	exit_received = 0;
53 	fflush(stdout);
54 	pid = fork();
55 	if (pid == 0) {
56 		printf("child %d\n", getpid());
57 		kill(getpid(), SIGSTOP);
58 		sleep(2);
59 		exit(1);
60 	}
61 
62 	while (!(cont_received && stop_received && exit_received)) {
63 		sleep(1);
64 		if (--count == 0)
65 			break;
66 	}
67 	if (!(cont_received && stop_received && exit_received))
68 		errx(1, "job signals lost");
69 
70 	printf("job control test OK.\n");
71 }
72 
73 void
74 rtsig_handler(int sig, siginfo_t *si, void *ctx)
75 {
76 }
77 
78 int
79 main()
80 {
81 	struct sigaction sa;
82 	sigset_t set;
83 	union sigval val;
84 
85 	/* test job control with empty signal queue */
86 	job_control_test();
87 
88 	/* now full fill signal queue in kernel */
89 	sigemptyset(&sa.sa_mask);
90 	sa.sa_flags = SA_SIGINFO;
91 	sa.sa_sigaction = rtsig_handler;
92 	sigaction(SIGRTMIN, &sa, NULL);
93 	sigemptyset(&set);
94 	sigaddset(&set, SIGRTMIN);
95 	sigprocmask(SIG_BLOCK, &set, NULL);
96 	val.sival_int = 1;
97 	while (sigqueue(getpid(), SIGRTMIN, val))
98 		;
99 
100 	/* signal queue is fully filled, test the job control again. */
101 	job_control_test();
102 	return (0);
103 }
104