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 50typedef void (*sighandler_t) (int); 51volatile int ready; 52 53#define BYTES 100 54#define SECS 10 55 56void setup(); 57void cleanup(); 58void do_child_1(); 59void do_child_2(); 60 61char *TCID = "msgctl07"; 62int TST_TOTAL = 1; 63 64/* Used by main() and do_child_1(): */ 65static int msqid; 66struct my_msgbuf { 67 long type; 68 char text[BYTES]; 69} p1_msgp, p2_msgp, p3_msgp, c1_msgp, c2_msgp, c3_msgp; 70 71int 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 207sighandler_t alrm(int sig LTP_ATTRIBUTE_UNUSED) 208{ 209 ready++; 210 return 0; 211} 212 213void 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 233void 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 278void 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 289void cleanup(void) 290{ 291 tst_rmdir(); 292} 293