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 42int parent_process(char *mqname, int read_pipe, int write_pipe, int child_pid); 43int child_process(char *mqname, int read_pipe, int write_pipe); 44int send_receive(int read_pipe, int write_pipe, char send, char *reply); 45 46int main() 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 } 83 else { 84 //parent process 85 close(to_parent[PIPE_WRITE]); 86 close(to_child[PIPE_READ]); 87 return parent_process(mqname, to_parent[PIPE_READ], 88 to_child[PIPE_WRITE], pid); 89 } 90} 91int 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: " "expected a 'd'\n"); 118 return PTS_UNRESOLVED; 119 } 120 if (mq_open(mqname, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR, 0) != -1) { 121 if (mq_unlink(mqname) != 0) { 122 perror(ERROR_PREFIX "mq_unlink(2)"); 123 return PTS_UNRESOLVED; 124 } 125 printf("Test PASSED\n"); 126 return PTS_PASS; 127 } 128 else { 129 printf("mq_open may fail until the message queue is 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 138int 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'"); 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', &reply); 158 if (rval) { 159 return rval; 160 } 161 if (reply != 'c') { 162 printf(ERROR_PREFIX "send_receive: " "expected a 'c'\n"); 163 return PTS_UNRESOLVED; 164 } 165 if (mq_close(mqdes) == -1) { 166 perror(ERROR_PREFIX "mq_close"); 167 return PTS_UNRESOLVED; 168 } 169 rval = send_receive(read_pipe, write_pipe, 'd', NULL); 170 if (rval) { 171 return rval; 172 } 173 return 0; 174} 175 176int send_receive(int read_pipe, int write_pipe, char send, char *reply) 177{ 178 ssize_t bytes; 179 if (send) { 180 bytes = write(write_pipe, &send, 1); 181 if (bytes == -1) { 182 perror(ERROR_PREFIX "write fd[1]"); 183 return PTS_UNRESOLVED; 184 } 185 } 186 if (reply) { 187 bytes = read(read_pipe, reply, 1); 188 if (bytes == -1) { 189 perror(ERROR_PREFIX "read fd[0]"); 190 return PTS_UNRESOLVED; 191 } else if (bytes == 0) { 192 printf(ERROR_PREFIX "read: EOF\n"); 193 return PTS_UNRESOLVED; 194 } 195 } 196 return 0; 197} 198