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
30int child_continued = 0;
31int waiting = 1;
32
33void handler(int signo, siginfo_t *info, void *context)
34{
35	if (info && info->si_code == CLD_CONTINUED) {
36		printf("Child has been stopped\n");
37		waiting = 0;
38		child_continued++;
39	}
40}
41
42
43int main()
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		/* POSIX specifies default action to be abnormal termination */
100		kill(pid, SIGHUP);
101		waitpid(pid, &s, 0);
102	}
103
104	if (child_continued == NUMSTOPS) {
105		printf("Test PASSED\n");
106		printf("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("In the section of the POSIX spec that describes the SA_NOCLDSTOP flag in the sigaction() interface "
118		"it is specified that if the SA_NOCLDSTOP flag is not set in sa_flags, then a SIGCHLD and a SIGCHLD "
119		"signal **MAY** be generated for the calling process whenever any of its stopped child processes are continued. "
120		"Because of that, this test will PASS either way, but note that the signals implementation you are currently "
121		"run this test on chooses NOT TO send a SIGCHLD signal whenever any of its stopped child processes are "
122		"continued. Again, this is not a bug because of the existence of the word *MAY* in the spec.\n");
123	return PTS_PASS;
124}
125
126