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