• 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 #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 		printf("fork() did not return success\n");
71 		return PTS_UNRESOLVED;
72 	} else if (pid == 0) {
73 		/* child */
74 		while (1) {
75 			/* wait forever, or until we are
76 			   interrupted by a signal */
77 			tv.tv_sec = 0;
78 			tv.tv_usec = 0;
79 			select(0, NULL, NULL, NULL, &tv);
80 		}
81 		return 0;
82 	} else {
83 		/* parent */
84 		int s;
85 		int i;
86 
87 		for (i = 0; i < NUMSTOPS; i++) {
88 			printf("--> Sending SIGSTOP\n");
89 			notification = 0;
90 			kill(pid, SIGSTOP);
91 
92 			/*
93 			   Don't let the kernel optimize away queued
94 			   SIGSTOP/SIGCONT signals.
95 			 */
96 
97 			wait_for_notification(CLD_STOPPED);
98 
99 			printf("--> Sending SIGCONT\n");
100 			notification = 0;
101 			kill(pid, SIGCONT);
102 			/*
103 			   SIGCHLD doesn't queue, make sure CLD_CONTINUED
104 			   doesn't mask the next CLD_STOPPED
105 			 */
106 			wait_for_notification(CLD_CONTINUED);
107 		}
108 
109 		kill(pid, SIGKILL);
110 		waitpid(pid, &s, 0);
111 	}
112 
113 	if (child_stopped == NUMSTOPS && child_continued == NUMSTOPS) {
114 		printf("Test PASSED\n");
115 		return 0;
116 	}
117 
118 	printf("Test FAILED\n");
119 	return -1;
120 }
121