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