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 /* 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