• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Check SIGCHLD siginfo_t decoding.
3  *
4  * Copyright (c) 2015-2016 Dmitry V. Levin <ldv@altlinux.org>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. The name of the author may not be used to endorse or promote products
16  *    derived from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #include "tests.h"
31 #include <assert.h>
32 #include <signal.h>
33 #include <string.h>
34 #include <unistd.h>
35 #include <sys/wait.h>
36 
37 static siginfo_t sinfo;
38 
39 static void
handler(int no,siginfo_t * si,void * uc)40 handler(int no, siginfo_t *si, void *uc)
41 {
42 	memcpy(&sinfo, si, sizeof(sinfo));
43 }
44 
45 int
main(void)46 main(void)
47 {
48 	tprintf("%s", "");
49 
50 	int fds[2];
51 	if (pipe(fds))
52 		perror_msg_and_fail("pipe");
53 
54 	pid_t pid = fork();
55 	if (pid < 0)
56 		perror_msg_and_fail("fork");
57 
58 	if (!pid) {
59 		char c;
60 		(void) close(1);
61 		assert(read(0, &c, sizeof(c)) == 1);
62 		return 42;
63 	}
64 
65 	(void) close(0);
66 
67 	struct sigaction sa = {
68 		.sa_sigaction = handler,
69 		.sa_flags = SA_SIGINFO
70 	};
71 	assert(sigaction(SIGCHLD, &sa, NULL) == 0);
72 
73 	sigset_t block_mask, unblock_mask;
74 	assert(sigprocmask(SIG_SETMASK, NULL, &block_mask) == 0);
75 	sigaddset(&block_mask, SIGCHLD);
76 	assert(sigprocmask(SIG_SETMASK, &block_mask, NULL) == 0);
77 
78 	unblock_mask = block_mask;
79 	sigdelset(&unblock_mask, SIGCHLD);
80 
81 	assert(write(1, "", 1) == 1);
82 	(void) close(1);
83 
84 	sigsuspend(&unblock_mask);
85 	tprintf("--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED"
86 		", si_pid=%d, si_uid=%u, si_status=%d"
87 		", si_utime=%llu, si_stime=%llu} ---\n",
88 		sinfo.si_pid, sinfo.si_uid, sinfo.si_status,
89 		zero_extend_signed_to_ull(sinfo.si_utime),
90 		zero_extend_signed_to_ull(sinfo.si_stime));
91 
92 	int s;
93 	assert(wait(&s) == pid);
94 	assert(WIFEXITED(s) && WEXITSTATUS(s) == 42);
95 
96 	if (pipe(fds))
97 		perror_msg_and_fail("pipe");
98 	pid = fork();
99 	if (pid < 0)
100 		perror_msg_and_fail("fork");
101 
102 	if (!pid) {
103 		(void) close(1);
104 		char c;
105 		assert(read(0, &c, sizeof(c)) == 1);
106 		(void) raise(SIGUSR1);
107 		return 1;
108 	}
109 
110 	(void) close(0);
111 
112 	assert(write(1, "", 1) == 1);
113 	(void) close(1);
114 
115 	sigsuspend(&unblock_mask);
116 	tprintf("--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_KILLED"
117 		", si_pid=%d, si_uid=%u, si_status=SIGUSR1"
118 		", si_utime=%llu, si_stime=%llu} ---\n",
119 		sinfo.si_pid, sinfo.si_uid,
120 		zero_extend_signed_to_ull(sinfo.si_utime),
121 		zero_extend_signed_to_ull(sinfo.si_stime));
122 
123 	assert(wait(&s) == pid);
124 	assert(WIFSIGNALED(s) && WTERMSIG(s) == SIGUSR1);
125 
126 	if (pipe(fds))
127 		perror_msg_and_fail("pipe");
128 	pid = fork();
129 	if (pid < 0)
130 		perror_msg_and_fail("fork");
131 
132 	if (!pid) {
133 		(void) close(1);
134 		raise(SIGSTOP);
135 		char c;
136 		assert(read(0, &c, sizeof(c)) == 1);
137 		return 0;
138 	}
139 
140 	(void) close(0);
141 
142 	sigsuspend(&unblock_mask);
143 	tprintf("--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_STOPPED"
144 		", si_pid=%d, si_uid=%u, si_status=SIGSTOP"
145 		", si_utime=%llu, si_stime=%llu} ---\n",
146 		sinfo.si_pid, sinfo.si_uid,
147 		zero_extend_signed_to_ull(sinfo.si_utime),
148 		zero_extend_signed_to_ull(sinfo.si_stime));
149 
150 	assert(kill(pid, SIGCONT) == 0);
151 
152 	sigsuspend(&unblock_mask);
153 	tprintf("--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_CONTINUED"
154 		", si_pid=%d, si_uid=%u, si_status=SIGCONT"
155 		", si_utime=%llu, si_stime=%llu} ---\n",
156 		sinfo.si_pid, sinfo.si_uid,
157 		zero_extend_signed_to_ull(sinfo.si_utime),
158 		zero_extend_signed_to_ull(sinfo.si_stime));
159 
160 	assert(write(1, "", 1) == 1);
161 	(void) close(1);
162 
163 	sigsuspend(&unblock_mask);
164 	tprintf("--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED"
165 		", si_pid=%d, si_uid=%u, si_status=0"
166 		", si_utime=%llu, si_stime=%llu} ---\n",
167 		sinfo.si_pid, sinfo.si_uid,
168 		zero_extend_signed_to_ull(sinfo.si_utime),
169 		zero_extend_signed_to_ull(sinfo.si_stime));
170 
171 	assert(wait(&s) == pid && s == 0);
172 
173 	tprintf("%s\n", "+++ exited with 0 +++");
174 	return 0;
175 }
176