1 /* 2 * Copyright (c) 2004, Bull S.A.. All rights reserved. 3 * Created by: Sebastien Decugis 4 * Copyright (c) 2011 Cyril Hrubis <chrubis (at) suse.cz> 5 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms of version 2 of the GNU General Public License as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it would be useful, but 11 * WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 13 * 14 * You should have received a copy of the GNU General Public License along 15 * with this program; if not, write the Free Software Foundation, Inc., 16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 18 * This sample test aims to check the following assertion: 19 * 20 * The opened message queue descriptors are copied to the child process and 21 * refer to the same object. 22 23 * The steps are: 24 * -> Open a message queue descriptor. 25 * -> Send a message to this descriptor. 26 * -> Fork 27 * -> Check if that the child's message count for this descriptor is 1. 28 * -> Unlink the message queue otherwise it will remain in the system. 29 30 * The test fails if the child reports 0 message count 31 * or if it fails to read the descriptor. 32 33 */ 34 35 /* We are testing conformance to IEEE Std 1003.1, 2003 Edition */ 36 #define _POSIX_C_SOURCE 200112L 37 38 #include <sys/stat.h> 39 #include <sys/wait.h> 40 #include <errno.h> 41 #include <fcntl.h> 42 #include <mqueue.h> 43 #include <pthread.h> 44 #include <stdarg.h> 45 #include <stdio.h> 46 #include <stdlib.h> 47 #include <string.h> 48 #include <unistd.h> 49 50 #include "posixtest.h" 51 52 static const char *queue_name = "/fork_19_1_mq"; 53 static const char message[] = "I'm your father..."; 54 55 int main(void) 56 { 57 int ret, status; 58 pid_t child, ctl; 59 60 mqd_t mq; 61 char rcv[sizeof(message)]; 62 63 struct mq_attr mqa; 64 65 /* Create a message queue descriptor */ 66 mqa.mq_maxmsg = 2; 67 mqa.mq_msgsize = sizeof(message); 68 69 mq = mq_open(queue_name, O_RDWR | O_CREAT | O_NONBLOCK, 70 S_IRUSR | S_IWUSR, &mqa); 71 72 if (mq == -1) { 73 perror("Failed to create the message queue descriptor"); 74 return PTS_UNRESOLVED; 75 } 76 77 /* Send 1 message to this message queue */ 78 ret = mq_send(mq, message, sizeof(message), 0); 79 80 if (ret != 0) { 81 mq_close(mq); 82 mq_unlink(queue_name); 83 perror("Failed to send the message"); 84 return PTS_UNRESOLVED; 85 } 86 87 /* Check the message has been queued */ 88 ret = mq_getattr(mq, &mqa); 89 90 if (ret != 0) { 91 mq_close(mq); 92 mq_unlink(queue_name); 93 perror("Failed to get message queue attributes"); 94 return PTS_UNRESOLVED; 95 } 96 97 if (mqa.mq_curmsgs != 1) { 98 mq_close(mq); 99 mq_unlink(queue_name); 100 printf("The queue information does not show the new message"); 101 return PTS_UNRESOLVED; 102 } 103 104 /* Create the child */ 105 child = fork(); 106 107 if (child == -1) { 108 mq_close(mq); 109 mq_unlink(queue_name); 110 perror("Failed to fork"); 111 return PTS_UNRESOLVED; 112 } 113 114 /* child */ 115 if (child == 0) { 116 ret = mq_getattr(mq, &mqa); 117 118 if (ret != 0) { 119 perror 120 ("Failed to get message queue attributes in child"); 121 return PTS_FAIL; 122 } 123 124 if (mqa.mq_curmsgs != 1) { 125 perror 126 ("The queue information does not show the message in child"); 127 return PTS_FAIL; 128 } 129 130 /* Now, receive the message */ 131 ret = mq_receive(mq, rcv, sizeof(rcv), NULL); 132 133 /* expected message size */ 134 if (ret != sizeof(message)) { 135 perror("Failed to receive the message"); 136 return PTS_UNRESOLVED; 137 } 138 139 printf("Received message: %s\n", rcv); 140 141 /* We're done */ 142 exit(PTS_PASS); 143 } 144 145 /* Parent joins the child */ 146 ctl = waitpid(child, &status, 0); 147 148 if (ctl != child) { 149 mq_close(mq); 150 mq_unlink(queue_name); 151 perror("Waitpid returned the wrong PID"); 152 return PTS_UNRESOLVED; 153 } 154 155 if (!WIFEXITED(status) || (WEXITSTATUS(status) != PTS_PASS)) { 156 mq_close(mq); 157 mq_unlink(queue_name); 158 printf("Child exited abnormally"); 159 return PTS_FAIL; 160 } 161 162 /* Check the message has been unqueued */ 163 ret = mq_getattr(mq, &mqa); 164 165 if (ret != 0) { 166 mq_close(mq); 167 mq_unlink(queue_name); 168 perror("Failed to get message queue attributes the 2nd time"); 169 return PTS_UNRESOLVED; 170 } 171 172 if (mqa.mq_curmsgs != 0) { 173 mq_close(mq); 174 mq_unlink(queue_name); 175 printf("The message received in child was not dequeued."); 176 return PTS_FAIL; 177 } 178 179 mq_close(mq); 180 mq_unlink(queue_name); 181 182 printf("Test passed\n"); 183 return PTS_PASS; 184 } 185