1 /*
2 * Copyright (c) 2002-2003, Intel Corporation. All rights reserved.
3 * Created by: Rusty.Lynch REMOVE-THIS AT intel DOT com
4 * This file is licensed under the GPL license. For the full content
5 * of this license, see the COPYING file at the top level of this
6 * source tree.
7
8 Test assertion #11 by verifying that SIGCHLD signals are sent to a parent
9 when their children are continued after being stopped.
10
11 NOTE: This is only required to work if the XSI options are implemented.
12 * 12/18/02 - Adding in include of sys/time.h per
13 * rodrigc REMOVE-THIS AT attbi DOT com input that it needs
14 * to be included whenever the timeval struct is used.
15 *
16 */
17
18 #include <signal.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <sys/select.h>
22 #include <sys/wait.h>
23 #include <sys/time.h>
24 #include <sys/types.h>
25 #include <unistd.h>
26 #include "posixtest.h"
27
28 #define NUMSTOPS 2
29
30 static volatile int child_continued;
31 static volatile int waiting = 1;
32
handler(int signo LTP_ATTRIBUTE_UNUSED,siginfo_t * info,void * context LTP_ATTRIBUTE_UNUSED)33 void handler(int signo LTP_ATTRIBUTE_UNUSED, siginfo_t *info,
34 void *context LTP_ATTRIBUTE_UNUSED)
35 {
36 if (info && info->si_code == CLD_CONTINUED) {
37 printf("Child has been stopped\n");
38 waiting = 0;
39 child_continued++;
40 }
41 }
42
main(void)43 int main(void)
44 {
45 pid_t pid;
46 struct sigaction act;
47 struct timeval tv;
48
49 act.sa_sigaction = handler;
50 act.sa_flags = SA_SIGINFO;
51 sigemptyset(&act.sa_mask);
52 sigaction(SIGCHLD, &act, 0);
53
54 if ((pid = fork()) == 0) {
55 /* child */
56 while (1) {
57 /* wait forever, or until we are
58 interrupted by a signal */
59 tv.tv_sec = 0;
60 tv.tv_usec = 0;
61 select(0, NULL, NULL, NULL, &tv);
62 }
63 return 0;
64 } else {
65 /* parent */
66 int s;
67 int i;
68
69 /* delay to allow child to get into select call */
70 tv.tv_sec = 1;
71 tv.tv_usec = 0;
72 select(0, NULL, NULL, NULL, &tv);
73
74 for (i = 0; i < NUMSTOPS; i++) {
75 struct timeval tv;
76 printf("--> Sending SIGSTOP\n");
77 kill(pid, SIGSTOP);
78
79 /*
80 Don't let the kernel optimize away queued
81 SIGSTOP/SIGCONT signals.
82 */
83 tv.tv_sec = 1;
84 tv.tv_usec = 0;
85 select(0, NULL, NULL, NULL, &tv);
86
87 printf("--> Sending SIGCONT\n");
88 waiting = 1;
89 kill(pid, SIGCONT);
90 while (waiting) {
91 tv.tv_sec = 1;
92 tv.tv_usec = 0;
93 if (!select(0, NULL, NULL, NULL, &tv))
94 break;
95 }
96
97 }
98
99 kill(pid, SIGKILL);
100 waitpid(pid, &s, 0);
101 }
102
103 if (child_continued == NUMSTOPS) {
104 printf("Test PASSED\n");
105 printf
106 ("In the section of the POSIX spec that describes the SA_NOCLDSTOP flag in the sigaction() interface "
107 "it is specified that if the SA_NOCLDSTOP flag is not set in sa_flags, then a SIGCHLD and a SIGCHLD "
108 "signal **MAY** be generated for the calling process whenever any of its stopped child processes are continued. "
109 "Because of that, this test will PASS either way, but note that the signals implementation you are currently "
110 "run this test on DOES choose to send a SIGCHLD signal whenever any of its stopped child processes are "
111 "continued. Again, this is not a bug because of the existence of the word *MAY* in the spec.\n");
112 return PTS_PASS;
113 }
114
115 printf("Test PASSED\n");
116
117 printf
118 ("In the section of the POSIX spec that describes the SA_NOCLDSTOP flag in the sigaction() interface "
119 "it is specified that if the SA_NOCLDSTOP flag is not set in sa_flags, then a SIGCHLD and a SIGCHLD "
120 "signal **MAY** be generated for the calling process whenever any of its stopped child processes are continued. "
121 "Because of that, this test will PASS either way, but note that the signals implementation you are currently "
122 "run this test on chooses NOT TO send a SIGCHLD signal whenever any of its stopped child processes are "
123 "continued. Again, this is not a bug because of the existence of the word *MAY* in the spec.\n");
124 return PTS_PASS;
125 }
126