Home | History | Annotate | Download | only in fork
      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