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
10 int stop_received;
11 int exit_received;
12 int cont_received;
13
14 void
job_handler(int sig,siginfo_t * si,void * ctx)15 job_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
38 void
job_control_test(void)39 job_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
72 void
rtsig_handler(int sig,siginfo_t * si,void * ctx)73 rtsig_handler(int sig, siginfo_t *si, void *ctx)
74 {
75 }
76
77 int
main()78 main()
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