Home | History | Annotate | Download | only in mq_open
      1 /*
      2  * Copyright (c) 2003, Intel Corporation. All rights reserved.
      3  * Created by:  julie.n.fleischer REMOVE-THIS AT intel DOT com
      4  * This file is licensed under the GPL license.  For the full content
      5  * of this license, see the COPYING file at the top level of this
      6  * source tree.
      7  */
      8 
      9 /*
     10  * Test that if the access mode is O_RDONLY, the message queue can
     11  * receive messages but not send.
     12  *
     13  * Test for a message queue opened twice in two different processes.
     14  *
     15  * 3/13/03 - Added fix from Gregoire Pichon for specifying an attr
     16  *           with a mq_maxmsg >= BUFFER.
     17  */
     18 
     19 #include <sys/stat.h>
     20 #include <sys/types.h>
     21 #include <sys/wait.h>
     22 #include <fcntl.h>
     23 #include <mqueue.h>
     24 #include <signal.h>
     25 #include <stdio.h>
     26 #include <string.h>
     27 #include <unistd.h>
     28 #include "posixtest.h"
     29 
     30 #define NAMESIZE 50
     31 #define MSGSTR "0123456789"
     32 #define BUFFER 40
     33 
     34 #define CHILDPASS 1
     35 #define CHILDFAIL 0
     36 
     37 void handler(int signo)
     38 {
     39 	(void) signo;
     40 	return;
     41 }
     42 
     43 int main(void)
     44 {
     45 	char qname[NAMESIZE];
     46 	const char *msgptr = MSGSTR;
     47 	int pid;
     48 
     49 	sprintf(qname, "/mq_open_7-2_%d", getpid());
     50 
     51 	pid = fork();
     52 	if (pid == 0) {
     53 		mqd_t roqueue;
     54 		char msgrcd[BUFFER];
     55 		sigset_t mask;
     56 		struct mq_attr attr;
     57 		struct sigaction act;
     58 		int sig;
     59 		unsigned pri;
     60 
     61 		/* child here */
     62 
     63 		/* Set up handler for SIGUSR1 */
     64 		act.sa_handler = handler;
     65 		act.sa_flags = 0;
     66 		sigaction(SIGUSR1, &act, NULL);
     67 
     68 		/* wait for parent to finish mq_send */
     69 		sigemptyset(&mask);
     70 		sigaddset(&mask, SIGUSR1);
     71 		sigprocmask(SIG_BLOCK, &mask, NULL);
     72 		sigwait(&mask, &sig);
     73 
     74 		/* once parent has finished sending, open read-only queue */
     75 		attr.mq_msgsize = BUFFER;
     76 		attr.mq_maxmsg = BUFFER;
     77 		roqueue = mq_open(qname, O_RDONLY, S_IRUSR | S_IWUSR, &attr);
     78 		if (roqueue == (mqd_t) - 1) {
     79 			perror("mq_open() read only failed");
     80 			return CHILDFAIL;
     81 		}
     82 #ifdef DEBUG
     83 		printf("Readonly message queue opened in child\n");
     84 #endif
     85 
     86 		if (mq_receive(roqueue, msgrcd, BUFFER, &pri) == -1) {
     87 			perror("mq_receive() on a read only queue failed");
     88 			mq_close(roqueue);
     89 			return CHILDFAIL;
     90 		}
     91 #ifdef DEBUG
     92 		printf("Received message %s\n", msgrcd);
     93 #endif
     94 
     95 		if (mq_send(roqueue, msgptr, strlen(msgptr) + 1, 1) == 0) {
     96 			printf("mq_send() on a read only queue succeeded\n");
     97 			mq_close(roqueue);
     98 			return CHILDFAIL;
     99 		}
    100 #ifdef DEBUG
    101 		printf("Sending message failed in child, as expected\n");
    102 #endif
    103 		mq_close(roqueue);
    104 
    105 		return CHILDPASS;
    106 	} else {
    107 		/* parent here */
    108 		mqd_t rdwrqueue;
    109 		struct mq_attr attr;
    110 		int i;
    111 
    112 		attr.mq_msgsize = BUFFER;
    113 		attr.mq_maxmsg = BUFFER;
    114 		rdwrqueue = mq_open(qname, O_CREAT | O_RDWR,
    115 				    S_IRUSR | S_IWUSR, &attr);
    116 		if (rdwrqueue == (mqd_t) - 1) {
    117 			perror("mq_open() did not return success");
    118 			printf("Test UNRESOLVED\n");
    119 			/* kill child and exit */
    120 			kill(pid, SIGABRT);
    121 			return PTS_UNRESOLVED;
    122 		}
    123 #ifdef DEBUG
    124 		printf("Message queue opened in parent\n");
    125 #endif
    126 
    127 		if (mq_send(rdwrqueue, msgptr, strlen(msgptr) + 1, 1) != 0) {
    128 			perror("mq_send() did not return success");
    129 			printf("Test UNRESOLVED\n");
    130 			/* close queue, kill child and exit */
    131 			mq_close(rdwrqueue);
    132 			mq_unlink(qname);
    133 			kill(pid, SIGABRT);
    134 			return PTS_UNRESOLVED;
    135 		}
    136 #ifdef DEBUG
    137 		printf("Message %s sent\n", msgptr);
    138 #endif
    139 
    140 		sleep(1);
    141 		kill(pid, SIGUSR1);
    142 
    143 		if (wait(&i) == -1) {
    144 			perror("Error waiting for child to exit");
    145 			printf("Test UNRESOLVED\n");
    146 			/* close queue and exit */
    147 			mq_close(rdwrqueue);
    148 			mq_unlink(qname);
    149 			return PTS_UNRESOLVED;
    150 		}
    151 #ifdef DEBUG
    152 		printf("Child finished\n");
    153 #endif
    154 
    155 		mq_close(rdwrqueue);
    156 		mq_unlink(qname);
    157 
    158 		if (!WIFEXITED(i) || !WEXITSTATUS(i)) {
    159 			printf("Test FAILED: exit status %d\n", i);
    160 			return PTS_FAIL;
    161 		}
    162 
    163 		printf("Test PASSED\n");
    164 		return PTS_PASS;
    165 	}
    166 
    167 	return PTS_UNRESOLVED;
    168 }
    169