1 /*
2 Test assertion #10 by verifying that SIGCHLD signals are sent to a parent
3 when their children are stopped.
4 * 12/18/02 - Adding in include of sys/time.h per
5 * rodrigc REMOVE-THIS AT attbi DOT com input that it needs
6 * to be included whenever the timeval struct is used.
7 *
8 */
9
10 #include <signal.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <sys/select.h>
14 #include <sys/wait.h>
15 #include <sys/time.h>
16 #include <sys/types.h>
17 #include <unistd.h>
18 #include "posixtest.h"
19
20 #define NUMSTOPS 10
21
22 static volatile int child_stopped;
23 static volatile int child_continued;
24 static volatile int notification;
25
handler(int signo PTS_ATTRIBUTE_UNUSED,siginfo_t * info,void * context PTS_ATTRIBUTE_UNUSED)26 static void handler(int signo PTS_ATTRIBUTE_UNUSED, siginfo_t *info,
27 void *context PTS_ATTRIBUTE_UNUSED)
28 {
29 if (!info)
30 return;
31
32 notification = info->si_code;
33
34 switch (notification) {
35 case CLD_STOPPED:
36 printf("Child has been stopped\n");
37 child_stopped++;
38 break;
39 case CLD_CONTINUED:
40 printf("Child has been continued\n");
41 child_continued++;
42 break;
43 }
44 }
45
wait_for_notification(int val)46 static void wait_for_notification(int val)
47 {
48 struct timeval tv;
49
50 while (notification != val) {
51 tv.tv_sec = 1;
52 tv.tv_usec = 0;
53 if (!select(0, NULL, NULL, NULL, &tv))
54 break;
55 }
56 }
57
main(void)58 int main(void)
59 {
60 pid_t pid;
61 struct sigaction act;
62 struct timeval tv;
63
64 act.sa_sigaction = handler;
65 act.sa_flags = SA_SIGINFO;
66 sigemptyset(&act.sa_mask);
67 sigaction(SIGCHLD, &act, 0);
68
69 if ((pid = fork()) == 0) {
70 /* child */
71 while (1) {
72 /* wait forever, or until we are
73 interrupted by a signal */
74 tv.tv_sec = 0;
75 tv.tv_usec = 0;
76 select(0, NULL, NULL, NULL, &tv);
77 }
78 return 0;
79 } else {
80 /* parent */
81 int s;
82 int i;
83
84 for (i = 0; i < NUMSTOPS; i++) {
85 printf("--> Sending SIGSTOP\n");
86 notification = 0;
87 kill(pid, SIGSTOP);
88
89 /*
90 Don't let the kernel optimize away queued
91 SIGSTOP/SIGCONT signals.
92 */
93
94 wait_for_notification(CLD_STOPPED);
95
96 printf("--> Sending SIGCONT\n");
97 notification = 0;
98 kill(pid, SIGCONT);
99 /*
100 SIGCHLD doesn't queue, make sure CLD_CONTINUED
101 doesn't mask the next CLD_STOPPED
102 */
103 wait_for_notification(CLD_CONTINUED);
104 }
105
106 kill(pid, SIGKILL);
107 waitpid(pid, &s, 0);
108 }
109
110 if (child_stopped == NUMSTOPS && child_continued == NUMSTOPS) {
111 printf("Test PASSED\n");
112 return 0;
113 }
114
115 printf("Test FAILED\n");
116 return -1;
117 }
118