• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
19 #define NUMSTOPS 10
20 
21 int child_stopped = 0;
22 int child_continued = 0;
23 int notification;
24 
handler(int signo,siginfo_t * info,void * context)25 void handler(int signo, siginfo_t * info, void *context)
26 {
27 	if (!info)
28 		return;
29 
30 	notification = info->si_code;
31 
32 	switch (notification) {
33 	case CLD_STOPPED:
34 		printf("Child has been stopped\n");
35 		child_stopped++;
36 		break;
37 	case CLD_CONTINUED:
38 		printf("Child has been continued\n");
39 		child_continued++;
40 		break;
41 	}
42 }
43 
wait_for_notification(int val)44 void wait_for_notification(int val)
45 {
46 	struct timeval tv;
47 
48 	while (notification != val) {
49 		tv.tv_sec = 1;
50 		tv.tv_usec = 0;
51 		if (!select(0, NULL, NULL, NULL, &tv))
52 			break;
53 	}
54 }
55 
main(void)56 int main(void)
57 {
58 	pid_t pid;
59 	struct sigaction act;
60 	struct timeval tv;
61 
62 	act.sa_sigaction = handler;
63 	act.sa_flags = SA_SIGINFO;
64 	sigemptyset(&act.sa_mask);
65 	sigaction(SIGCHLD, &act, 0);
66 
67 	if ((pid = fork()) == 0) {
68 		/* child */
69 		while (1) {
70 			/* wait forever, or until we are
71 			   interrupted by a signal */
72 			tv.tv_sec = 0;
73 			tv.tv_usec = 0;
74 			select(0, NULL, NULL, NULL, &tv);
75 		}
76 		return 0;
77 	} else {
78 		/* parent */
79 		int s;
80 		int i;
81 
82 		for (i = 0; i < NUMSTOPS; i++) {
83 			printf("--> Sending SIGSTOP\n");
84 			notification = 0;
85 			kill(pid, SIGSTOP);
86 
87 			/*
88 			   Don't let the kernel optimize away queued
89 			   SIGSTOP/SIGCONT signals.
90 			 */
91 
92 			wait_for_notification(CLD_STOPPED);
93 
94 			printf("--> Sending SIGCONT\n");
95 			notification = 0;
96 			kill(pid, SIGCONT);
97 			/*
98 			   SIGCHLD doesn't queue, make sure CLD_CONTINUED
99 			   doesn't mask the next CLD_STOPPED
100 			 */
101 			wait_for_notification(CLD_CONTINUED);
102 		}
103 
104 		kill(pid, SIGKILL);
105 		waitpid(pid, &s, 0);
106 	}
107 
108 	if (child_stopped == NUMSTOPS && child_continued == NUMSTOPS) {
109 		printf("Test PASSED\n");
110 		return 0;
111 	}
112 
113 	printf("Test FAILED\n");
114 	return -1;
115 }
116