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 mq_unlink the mq and tell Child to close this mq.
     20  *  5. Child close the mq and tell parent.
     21  *  6. Parent recreate the mq using mq_open, if the mq is actually removed, this operation
     22  *     will succeed, if not, it may fail.
     23  */
     24 
     25 #include <signal.h>
     26 #include <stdio.h>
     27 #include <errno.h>
     28 #include <mqueue.h>
     29 #include <fcntl.h>
     30 #include <sys/stat.h>
     31 #include <sys/types.h>
     32 #include <unistd.h>
     33 #include "posixtest.h"
     34 
     35 #define PIPE_READ  0
     36 #define PIPE_WRITE 1
     37 
     38 #define TEST "2-2"
     39 #define FUNCTION "mq_unlink"
     40 #define ERROR_PREFIX "unexpected error: " FUNCTION " " TEST ": "
     41 
     42 int parent_process(char *mqname, int read_pipe, int write_pipe, int child_pid);
     43 int child_process(char *mqname, int read_pipe, int write_pipe);
     44 int send_receive(int read_pipe, int write_pipe, char send, char *reply);
     45 
     46 int main(void)
     47 {
     48 	char mqname[50];
     49 	pid_t pid;
     50 	int to_parent[2];
     51 	int to_child[2];
     52 	int rval;
     53 	struct sigaction sa;
     54 
     55 	sa.sa_handler = SIG_IGN;
     56 	sa.sa_flags = 0;
     57 	sigemptyset(&sa.sa_mask);
     58 	sigaction(SIGCHLD, &sa, NULL);
     59 
     60 	sprintf(mqname, "/" FUNCTION "_" TEST "_%d", getpid());
     61 	rval = pipe(to_parent);
     62 	if (rval == -1) {
     63 		perror(ERROR_PREFIX "fd[0]");
     64 		return PTS_UNRESOLVED;
     65 	}
     66 	rval = pipe(to_child);
     67 	if (rval == -1) {
     68 		perror(ERROR_PREFIX "fd[1]");
     69 		return PTS_UNRESOLVED;
     70 	}
     71 	pid = fork();
     72 	if (pid == -1) {
     73 		perror(ERROR_PREFIX "fork");
     74 		return PTS_UNRESOLVED;
     75 	}
     76 	if (pid == 0) {
     77 		//child process
     78 		close(to_parent[PIPE_READ]);
     79 		close(to_child[PIPE_WRITE]);
     80 		return child_process(mqname, to_child[PIPE_READ],
     81 				     to_parent[PIPE_WRITE]);
     82 	} else {
     83 		//parent process
     84 		close(to_parent[PIPE_WRITE]);
     85 		close(to_child[PIPE_READ]);
     86 		return parent_process(mqname, to_parent[PIPE_READ],
     87 				      to_child[PIPE_WRITE], pid);
     88 	}
     89 }
     90 
     91 int parent_process(char *mqname, int read_pipe, int write_pipe, int child_pid)
     92 {
     93 	mqd_t mqdes;
     94 	char reply;
     95 	int rval;
     96 
     97 	mqdes = mq_open(mqname, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR, 0);
     98 	if (mqdes == (mqd_t) - 1) {
     99 		perror(ERROR_PREFIX "mq_open");
    100 		return PTS_UNRESOLVED;
    101 	}
    102 	// Tell child a message queue has been opened.
    103 	rval = send_receive(read_pipe, write_pipe, 'a', &reply);
    104 	if (rval) {
    105 		return rval;
    106 	}
    107 	if (reply != 'b') {
    108 		printf(ERROR_PREFIX "send_receive: " "expected a 'b'\n");
    109 		return PTS_UNRESOLVED;
    110 	}
    111 	if (mq_unlink(mqname) == 0) {
    112 		rval = send_receive(read_pipe, write_pipe, 'c', &reply);
    113 		if (rval) {
    114 			return rval;
    115 		}
    116 		if (reply != 'd') {
    117 			printf(ERROR_PREFIX "send_receive: "
    118 			       "expected a 'd'\n");
    119 			return PTS_UNRESOLVED;
    120 		}
    121 		if (mq_open(mqname, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR, 0) !=
    122 		    -1) {
    123 			if (mq_unlink(mqname) != 0) {
    124 				perror(ERROR_PREFIX "mq_unlink(2)");
    125 				return PTS_UNRESOLVED;
    126 			}
    127 			printf("Test PASSED\n");
    128 			return PTS_PASS;
    129 		} else {
    130 			printf
    131 			    ("mq_open may fail until the message queue is actually removed \n");
    132 			printf("Test PASSED\n");
    133 			return PTS_PASS;
    134 		}
    135 	}
    136 	printf(ERROR_PREFIX "mq_unlink\n");
    137 	return PTS_UNRESOLVED;
    138 }
    139 
    140 int child_process(char *mqname, int read_pipe, int write_pipe)
    141 {
    142 	mqd_t mqdes;
    143 	int rval;
    144 	char reply;
    145 
    146 	rval = send_receive(read_pipe, write_pipe, 0, &reply);
    147 	if (rval) {
    148 		return rval;
    149 	}
    150 	if (reply != 'a') {
    151 		printf(ERROR_PREFIX "send_receive: " "expected an 'a'");
    152 		return PTS_UNRESOLVED;
    153 	}
    154 	mqdes = mq_open(mqname, O_RDWR, 0, 0);
    155 	if (mqdes == (mqd_t) - 1) {
    156 		perror(ERROR_PREFIX "mq_open");
    157 		return PTS_UNRESOLVED;
    158 	}
    159 	rval = send_receive(read_pipe, write_pipe, 'b', &reply);
    160 	if (rval) {
    161 		return rval;
    162 	}
    163 	if (reply != 'c') {
    164 		printf(ERROR_PREFIX "send_receive: " "expected a 'c'\n");
    165 		return PTS_UNRESOLVED;
    166 	}
    167 	if (mq_close(mqdes) == -1) {
    168 		perror(ERROR_PREFIX "mq_close");
    169 		return PTS_UNRESOLVED;
    170 	}
    171 	rval = send_receive(read_pipe, write_pipe, 'd', NULL);
    172 	if (rval) {
    173 		return rval;
    174 	}
    175 	return 0;
    176 }
    177 
    178 int send_receive(int read_pipe, int write_pipe, char send, char *reply)
    179 {
    180 	ssize_t bytes;
    181 	if (send) {
    182 		bytes = write(write_pipe, &send, 1);
    183 		if (bytes == -1) {
    184 			perror(ERROR_PREFIX "write fd[1]");
    185 			return PTS_UNRESOLVED;
    186 		}
    187 	}
    188 	if (reply) {
    189 		bytes = read(read_pipe, reply, 1);
    190 		if (bytes == -1) {
    191 			perror(ERROR_PREFIX "read fd[0]");
    192 			return PTS_UNRESOLVED;
    193 		} else if (bytes == 0) {
    194 			printf(ERROR_PREFIX "read: EOF\n");
    195 			return PTS_UNRESOLVED;
    196 		}
    197 	}
    198 	return 0;
    199 }
    200