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 36 #include <sys/stat.h> 37 #include <sys/wait.h> 38 #include <errno.h> 39 #include <fcntl.h> 40 #include <mqueue.h> 41 #include <pthread.h> 42 #include <stdarg.h> 43 #include <stdio.h> 44 #include <stdlib.h> 45 #include <string.h> 46 #include <unistd.h> 47 48 #include "posixtest.h" 49 50 static const char *queue_name = "/fork_19_1_mq"; 51 static const char message[] = "I'm your father..."; 52 53 int main(void) 54 { 55 int ret, status; 56 pid_t child, ctl; 57 58 mqd_t mq; 59 char rcv[sizeof(message)]; 60 61 struct mq_attr mqa; 62 63 /* Create a message queue descriptor */ 64 mqa.mq_maxmsg = 2; 65 mqa.mq_msgsize = sizeof(message); 66 67 mq = mq_open(queue_name, O_RDWR | O_CREAT | O_NONBLOCK, 68 S_IRUSR | S_IWUSR, &mqa); 69 70 if (mq == -1) { 71 perror("Failed to create the message queue descriptor"); 72 return PTS_UNRESOLVED; 73 } 74 75 /* Send 1 message to this message queue */ 76 ret = mq_send(mq, message, sizeof(message), 0); 77 78 if (ret != 0) { 79 mq_close(mq); 80 mq_unlink(queue_name); 81 perror("Failed to send the message"); 82 return PTS_UNRESOLVED; 83 } 84 85 /* Check the message has been queued */ 86 ret = mq_getattr(mq, &mqa); 87 88 if (ret != 0) { 89 mq_close(mq); 90 mq_unlink(queue_name); 91 perror("Failed to get message queue attributes"); 92 return PTS_UNRESOLVED; 93 } 94 95 if (mqa.mq_curmsgs != 1) { 96 mq_close(mq); 97 mq_unlink(queue_name); 98 printf("The queue information does not show the new message"); 99 return PTS_UNRESOLVED; 100 } 101 102 /* Create the child */ 103 child = fork(); 104 105 if (child == -1) { 106 mq_close(mq); 107 mq_unlink(queue_name); 108 perror("Failed to fork"); 109 return PTS_UNRESOLVED; 110 } 111 112 /* child */ 113 if (child == 0) { 114 ret = mq_getattr(mq, &mqa); 115 116 if (ret != 0) { 117 perror 118 ("Failed to get message queue attributes in child"); 119 return PTS_FAIL; 120 } 121 122 if (mqa.mq_curmsgs != 1) { 123 perror 124 ("The queue information does not show the message in child"); 125 return PTS_FAIL; 126 } 127 128 /* Now, receive the message */ 129 ret = mq_receive(mq, rcv, sizeof(rcv), NULL); 130 131 /* expected message size */ 132 if (ret != sizeof(message)) { 133 perror("Failed to receive the message"); 134 return PTS_UNRESOLVED; 135 } 136 137 printf("Received message: %s\n", rcv); 138 139 /* We're done */ 140 exit(PTS_PASS); 141 } 142 143 /* Parent joins the child */ 144 ctl = waitpid(child, &status, 0); 145 146 if (ctl != child) { 147 mq_close(mq); 148 mq_unlink(queue_name); 149 perror("Waitpid returned the wrong PID"); 150 return PTS_UNRESOLVED; 151 } 152 153 if (!WIFEXITED(status) || (WEXITSTATUS(status) != PTS_PASS)) { 154 mq_close(mq); 155 mq_unlink(queue_name); 156 printf("Child exited abnormally"); 157 return PTS_FAIL; 158 } 159 160 /* Check the message has been unqueued */ 161 ret = mq_getattr(mq, &mqa); 162 163 if (ret != 0) { 164 mq_close(mq); 165 mq_unlink(queue_name); 166 perror("Failed to get message queue attributes the 2nd time"); 167 return PTS_UNRESOLVED; 168 } 169 170 if (mqa.mq_curmsgs != 0) { 171 mq_close(mq); 172 mq_unlink(queue_name); 173 printf("The message received in child was not dequeued."); 174 return PTS_FAIL; 175 } 176 177 mq_close(mq); 178 mq_unlink(queue_name); 179 180 printf("Test passed\n"); 181 return PTS_PASS; 182 } 183