• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  *   Copyright (c) International Business Machines  Corp., 2002
4  *
5  *   This program is free software;  you can redistribute it and/or modify
6  *   it under the terms of the GNU General Public License as published by
7  *   the Free Software Foundation; either version 2 of the License, or
8  *   (at your option) any later version.
9  *
10  *   This program is distributed in the hope that it will be useful,
11  *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13  *   the GNU General Public License for more details.
14  *
15  *   You should have received a copy of the GNU General Public License
16  *   along with this program;  if not, write to the Free Software
17  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19 
20 /* 06/30/2001	Port to Linux	nsharoff@us.ibm.com */
21 /* 11/06/2002   Port to LTP     dbarrera@us.ibm.com */
22 /* 12/03/2008   Fix concurrency issue     mfertre@irisa.fr */
23 
24 /*
25  * NAME
26  *	msgctl07
27  *
28  * CALLS
29  *	msgget(2) msgctl(2) msgop(2)
30  *
31  * ALGORITHM
32  *	Get and manipulate a message queue.
33  *
34  * RESTRICTIONS
35  *
36  */
37 
38 #include <sys/types.h>
39 #include <sys/ipc.h>
40 #include <sys/msg.h>
41 #include <signal.h>
42 #include <sys/wait.h>
43 #include <stdio.h>
44 #include "test.h"
45 #include "ipcmsg.h"
46 #include <stdlib.h>
47 #include <unistd.h>
48 #include <errno.h>
49 
50 typedef void (*sighandler_t) (int);
51 volatile int ready;
52 
53 #define BYTES 100
54 #define SECS 10
55 
56 void setup();
57 void cleanup();
58 void do_child_1();
59 void do_child_2();
60 
61 char *TCID = "msgctl07";
62 int TST_TOTAL = 1;
63 
64 /* Used by main() and do_child_1(): */
65 static int msqid;
66 struct my_msgbuf {
67 	long type;
68 	char text[BYTES];
69 } p1_msgp, p2_msgp, p3_msgp, c1_msgp, c2_msgp, c3_msgp;
70 
main(int argc,char * argv[])71 int main(int argc, char *argv[])
72 {
73 	key_t key;
74 	int pid, status;
75 	int i, j, k;
76 	sighandler_t alrm();
77 
78 	tst_parse_opts(argc, argv, NULL, NULL);
79 
80 	setup();
81 
82 	key = getipckey();
83 	if ((msqid = msgget(key, IPC_CREAT | IPC_EXCL)) == -1) {
84 		tst_brkm(TFAIL | TERRNO, NULL, "msgget() failed");
85 
86 	}
87 
88 	pid = FORK_OR_VFORK();
89 	if (pid < 0) {
90 		(void)msgctl(msqid, IPC_RMID, NULL);
91 		tst_brkm(TFAIL, NULL,
92 			 "\tFork failed (may be OK if under stress)");
93 	} else if (pid == 0) {
94 		do_child_1();
95 	} else {
96 		struct sigaction act;
97 
98 		memset(&act, 0, sizeof(act));
99 		act.sa_handler = (sighandler_t) alrm;
100 		sigemptyset(&act.sa_mask);
101 		sigaddset(&act.sa_mask, SIGALRM);
102 		if ((sigaction(SIGALRM, &act, NULL)) < 0) {
103 			tst_resm(TFAIL | TERRNO, "signal failed");
104 			kill(pid, SIGKILL);
105 			(void)msgctl(msqid, IPC_RMID, NULL);
106 			tst_exit();
107 		}
108 		ready = 0;
109 		alarm(SECS);
110 		while (!ready)	/* make the child wait */
111 			usleep(50000);
112 		for (i = 0; i < BYTES; i++)
113 			p1_msgp.text[i] = 'i';
114 		p1_msgp.type = 1;
115 		if (msgsnd(msqid, &p1_msgp, BYTES, 0) == -1) {
116 			tst_resm(TFAIL | TERRNO, "msgsnd() failed");
117 			kill(pid, SIGKILL);
118 			(void)msgctl(msqid, IPC_RMID, NULL);
119 			tst_exit();
120 		}
121 		wait(&status);
122 	}
123 	if ((status >> 8) == 1) {
124 		tst_brkm(TFAIL, NULL, "test failed. status = %d",
125 			 (status >> 8));
126 	}
127 
128 	pid = FORK_OR_VFORK();
129 	if (pid < 0) {
130 		(void)msgctl(msqid, IPC_RMID, NULL);
131 		tst_brkm(TFAIL, NULL,
132 			 "\tFork failed (may be OK if under stress)");
133 	} else if (pid == 0) {
134 		do_child_2();
135 	} else {
136 		struct sigaction act;
137 
138 		memset(&act, 0, sizeof(act));
139 		act.sa_handler = (sighandler_t) alrm;
140 		sigemptyset(&act.sa_mask);
141 		sigaddset(&act.sa_mask, SIGALRM);
142 		if ((sigaction(SIGALRM, &act, NULL)) < 0) {
143 			tst_resm(TFAIL | TERRNO, "signal failed");
144 			kill(pid, SIGKILL);
145 			(void)msgctl(msqid, IPC_RMID, NULL);
146 			tst_exit();
147 		}
148 		ready = 0;
149 		alarm(SECS);
150 		while (!ready)	/* make the child wait */
151 			usleep(50000);
152 		for (i = 0; i < BYTES; i++)
153 			p1_msgp.text[i] = 'i';
154 		p1_msgp.type = 1;
155 		if (msgsnd(msqid, &p1_msgp, BYTES, 0) == -1) {
156 			tst_resm(TFAIL | TERRNO, "msgsnd() failed");
157 			kill(pid, SIGKILL);
158 			(void)msgctl(msqid, IPC_RMID, NULL);
159 			tst_exit();
160 		}
161 		for (j = 0; j < BYTES; j++)
162 			p2_msgp.text[j] = 'j';
163 		p2_msgp.type = 2;
164 		if (msgsnd(msqid, &p2_msgp, BYTES, 0) == -1) {
165 			tst_resm(TFAIL | TERRNO, "msgsnd() failed");
166 			kill(pid, SIGKILL);
167 			(void)msgctl(msqid, IPC_RMID, NULL);
168 			tst_exit();
169 		}
170 		for (k = 0; k < BYTES; k++)
171 			p3_msgp.text[k] = 'k';
172 		p3_msgp.type = 3;
173 		if (msgsnd(msqid, &p3_msgp, BYTES, 0) == -1) {
174 			tst_resm(TFAIL | TERRNO, "msgsnd() failed");
175 			kill(pid, SIGKILL);
176 			(void)msgctl(msqid, IPC_RMID, NULL);
177 			tst_exit();
178 		}
179 		wait(&status);
180 	}
181 	if ((status >> 8) == 1) {
182 		tst_brkm(TFAIL, NULL, "test failed. status = %d",
183 			 (status >> 8));
184 	}
185 	/*
186 	 * Remove the message queue from the system
187 	 */
188 #ifdef DEBUG
189 	tst_resm(TINFO, "Removing the message queue");
190 #endif
191 	fflush(stdout);
192 	(void)msgctl(msqid, IPC_RMID, NULL);
193 	if ((status = msgctl(msqid, IPC_STAT, NULL)) != -1) {
194 		(void)msgctl(msqid, IPC_RMID, NULL);
195 		tst_brkm(TFAIL, NULL, "msgctl(msqid, IPC_RMID) failed");
196 
197 	}
198 
199 	fflush(stdout);
200 	tst_resm(TPASS, "msgctl07 ran successfully!");
201 
202 	cleanup();
203 
204 	tst_exit();
205 }
206 
alrm(int sig LTP_ATTRIBUTE_UNUSED)207 sighandler_t alrm(int sig LTP_ATTRIBUTE_UNUSED)
208 {
209 	ready++;
210 	return 0;
211 }
212 
do_child_1(void)213 void do_child_1(void)
214 {
215 	int i;
216 	int size;
217 
218 	if ((size = msgrcv(msqid, &c1_msgp, BYTES, 0, 0)) == -1) {
219 		tst_brkm(TFAIL | TERRNO, NULL, "msgrcv() failed");
220 	}
221 	if (size != BYTES) {
222 		tst_brkm(TFAIL, NULL, "error: received %d bytes expected %d",
223 			 size,
224 			 BYTES);
225 	}
226 	for (i = 0; i < BYTES; i++)
227 		if (c1_msgp.text[i] != 'i') {
228 			tst_brkm(TFAIL, NULL, "error: corrup message");
229 		}
230 	exit(0);
231 }
232 
do_child_2(void)233 void do_child_2(void)
234 {
235 	int i, j, k;
236 	int size;
237 
238 	if ((size = msgrcv(msqid, &c3_msgp, BYTES, 3, 0)) == -1) {
239 		tst_brkm(TFAIL | TERRNO, NULL, "msgrcv() failed");
240 	}
241 	if (size != BYTES) {
242 		tst_brkm(TFAIL, NULL, "error: received %d bytes expected %d",
243 			 size,
244 			 BYTES);
245 	}
246 	for (k = 0; k < BYTES; k++)
247 		if (c3_msgp.text[k] != 'k') {
248 			tst_brkm(TFAIL, NULL, "error: corrupt message");
249 		}
250 	if ((size = msgrcv(msqid, &c2_msgp, BYTES, 2, 0)) == -1) {
251 		tst_brkm(TFAIL | TERRNO, NULL, "msgrcv() failed");
252 	}
253 	if (size != BYTES) {
254 		tst_brkm(TFAIL, NULL, "error: received %d bytes expected %d",
255 			 size,
256 			 BYTES);
257 	}
258 	for (j = 0; j < BYTES; j++)
259 		if (c2_msgp.text[j] != 'j') {
260 			tst_brkm(TFAIL, NULL, "error: corrupt message");
261 		}
262 	if ((size = msgrcv(msqid, &c1_msgp, BYTES, 1, 0)) == -1) {
263 		tst_brkm(TFAIL | TERRNO, NULL, "msgrcv() failed");
264 	}
265 	if (size != BYTES) {
266 		tst_brkm(TFAIL, NULL, "error: received %d bytes expected %d",
267 			 size,
268 			 BYTES);
269 	}
270 	for (i = 0; i < BYTES; i++)
271 		if (c1_msgp.text[i] != 'i') {
272 			tst_brkm(TFAIL, NULL, "error: corrupt message");
273 		}
274 
275 	exit(0);
276 }
277 
setup(void)278 void setup(void)
279 {
280 	tst_sig(FORK, DEF_HANDLER, cleanup);
281 
282 	tst_require_root();
283 
284 	TEST_PAUSE;
285 
286 	tst_tmpdir();
287 }
288 
cleanup(void)289 void cleanup(void)
290 {
291 	tst_rmdir();
292 }
293