Home | History | Annotate | Download | only in mq_unlink
      1 /*
      2  * Copyright (c) 2003, Intel Corporation. All rights reserved.
      3  * Created by:  crystal.xiong 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  *  mq_unlink() test plan:
     11  *  If one or more process have the message queue open, destruction of the
     12  *  message queue will be postponed until all reference to the message queue
     13  *  have been closed. At this time, call to mq_open() with O_CREAT flag may fail
     14  *  until the message queue is actually removed.
     15  *  Steps:
     16  *  1. Create 2 pipes to communicate with parent and child processes.
     17  *  2. Parent uses mq_open to create a new mq and tell child to open it using pipe.
     18  *  3. Child open the mq and tell parent, so mq has 2 reference now.
     19  *  4. Parent want to mq_unlink the mq, since Child does not close the mq,
     20  *     mq_unlink will postpone. At this time, if using mq_open to create
     21  *     a new mq with the same name, mq_open may fail.
     22  *
     23  *     3/27/2003    Fixed a bug pointed by Krzysztof Benedyczak and
     24  *     		    Gregoire Pichon. mq_open may fail in this case. Not
     25  *     		    must fail.
     26  */
     27 
     28 #include <signal.h>
     29 #include <stdio.h>
     30 #include <errno.h>
     31 #include <mqueue.h>
     32 #include <fcntl.h>
     33 #include <sys/stat.h>
     34 #include <sys/types.h>
     35 #include <unistd.h>
     36 #include "posixtest.h"
     37 
     38 #define PIPE_READ  0
     39 #define PIPE_WRITE 1
     40 
     41 #define TEST "2-1"
     42 #define FUNCTION "mq_unlink"
     43 #define ERROR_PREFIX "unexpected error: " FUNCTION " " TEST ": "
     44 
     45 #define NAMESIZE	50
     46 
     47 int parent_process(char *mqname, int read_pipe, int write_pipe, int child_pid);
     48 int child_process(char *mqname, int read_pipe, int write_pipe);
     49 int send_receive(int read_pipe, int write_pipe, char send, char *reply);
     50 
     51 int main(void)
     52 {
     53 	char mqname[NAMESIZE];
     54 	pid_t pid;
     55 	int to_parent[2];
     56 	int to_child[2];
     57 	int rval;
     58 	struct sigaction sa;
     59 
     60 	sa.sa_handler = SIG_IGN;
     61 	sa.sa_flags = 0;
     62 	sigemptyset(&sa.sa_mask);
     63 	sigaction(SIGCHLD, &sa, NULL);
     64 
     65 	sprintf(mqname, "/" FUNCTION "_" TEST "_%d", getpid());
     66 	rval = pipe(to_parent);
     67 	if (rval == -1) {
     68 		perror(ERROR_PREFIX "fd[0]");
     69 		return PTS_UNRESOLVED;
     70 	}
     71 	rval = pipe(to_child);
     72 	if (rval == -1) {
     73 		perror(ERROR_PREFIX "fd[1]");
     74 		return PTS_UNRESOLVED;
     75 	}
     76 	pid = fork();
     77 	if (pid == -1) {
     78 		perror(ERROR_PREFIX "fork");
     79 		return PTS_UNRESOLVED;
     80 	}
     81 	if (pid == 0) {
     82 		//child process
     83 		close(to_parent[PIPE_READ]);
     84 		close(to_child[PIPE_WRITE]);
     85 		return child_process(mqname, to_child[PIPE_READ],
     86 				     to_parent[PIPE_WRITE]);
     87 	} else {
     88 		//parent process
     89 		close(to_parent[PIPE_WRITE]);
     90 		close(to_child[PIPE_READ]);
     91 		return parent_process(mqname, to_parent[PIPE_READ],
     92 				      to_child[PIPE_WRITE], pid);
     93 	}
     94 }
     95 
     96 int parent_process(char *mqname, int read_pipe, int write_pipe, int child_pid)
     97 {
     98 	mqd_t mqdes;
     99 	char reply;
    100 	int rval;
    101 
    102 	mqdes = mq_open(mqname, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR, 0);
    103 	if (mqdes == (mqd_t) - 1) {
    104 		perror(ERROR_PREFIX "mq_open");
    105 		return PTS_UNRESOLVED;
    106 	}
    107 	// Tell child a message queue has been opened.
    108 	rval = send_receive(read_pipe, write_pipe, 'a', &reply);
    109 	if (rval) {
    110 		return rval;
    111 	}
    112 	if (reply != 'b') {
    113 		printf(ERROR_PREFIX "send_receive: " "expected a 'b'");
    114 		return PTS_UNRESOLVED;
    115 	}
    116 	if (mq_unlink(mqname) == 0) {
    117 		if (mq_open(mqname, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR, 0) ==
    118 		    -1) {
    119 			printf
    120 			    ("mq_open to recreate the message	mqueue may fail until all references to the message queue have been closed, or until the message queue is actually removed. \n");
    121 			printf("Test PASSED\n");
    122 			return PTS_PASS;
    123 		} else {
    124 			if (mq_unlink(mqname) != 0) {
    125 				printf(ERROR_PREFIX "mq_unlink(2)");
    126 				return PTS_UNRESOLVED;
    127 			}
    128 			printf
    129 			    ("mq_open to recreate the message	mqueue may succeed even if the references to the message queue have not been closed or the message queue is not actually removed. \n");
    130 			printf("Test PASSED\n");
    131 			return PTS_PASS;
    132 		}
    133 	}
    134 	printf(ERROR_PREFIX "mq_unlink \n");
    135 	return PTS_UNRESOLVED;
    136 }
    137 
    138 int child_process(char *mqname, int read_pipe, int write_pipe)
    139 {
    140 	mqd_t mqdes;
    141 	int rval;
    142 	char reply;
    143 
    144 	rval = send_receive(read_pipe, write_pipe, 0, &reply);
    145 	if (rval) {
    146 		return rval;
    147 	}
    148 	if (reply != 'a') {
    149 		printf(ERROR_PREFIX "send_receive: " "expected an 'a'\n");
    150 		return PTS_UNRESOLVED;
    151 	}
    152 	mqdes = mq_open(mqname, O_RDWR, 0, 0);
    153 	if (mqdes == (mqd_t) - 1) {
    154 		perror(ERROR_PREFIX "mq_open");
    155 		return PTS_UNRESOLVED;
    156 	}
    157 	rval = send_receive(read_pipe, write_pipe, 'b', NULL);
    158 
    159 	return 0;
    160 }
    161 
    162 int send_receive(int read_pipe, int write_pipe, char send, char *reply)
    163 {
    164 	ssize_t bytes;
    165 
    166 	if (send) {
    167 		bytes = write(write_pipe, &send, 1);
    168 		if (bytes == -1) {
    169 			perror(ERROR_PREFIX "write fd[1]");
    170 			return PTS_UNRESOLVED;
    171 		}
    172 	}
    173 	if (reply) {
    174 		bytes = read(read_pipe, reply, 1);
    175 		if (bytes == -1) {
    176 			perror(ERROR_PREFIX "read fd[0]");
    177 			return PTS_UNRESOLVED;
    178 		} else if (bytes == 0) {
    179 			printf(ERROR_PREFIX "read: EOF \n");
    180 			return PTS_UNRESOLVED;
    181 		}
    182 	}
    183 	return 0;
    184 }
    185