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