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 47int parent_process(char *mqname, int read_pipe, int write_pipe, int child_pid); 48int child_process(char *mqname, int read_pipe, int write_pipe); 49int send_receive(int read_pipe, int write_pipe, char send, char *reply); 50 51int main() 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 } 88 else { 89 //parent process 90 close(to_parent[PIPE_WRITE]); 91 close(to_child[PIPE_READ]); 92 return parent_process(mqname, to_parent[PIPE_READ], 93 to_child[PIPE_WRITE], pid); 94 } 95} 96int 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) == -1) { 118 printf("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"); 119 printf("Test PASSED\n"); 120 return PTS_PASS; 121 } 122 else { 123 if (mq_unlink(mqname) != 0) { 124 printf(ERROR_PREFIX "mq_unlink(2)"); 125 return PTS_UNRESOLVED; 126 } 127 printf("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"); 128 printf("Test PASSED\n"); 129 return PTS_PASS; 130 } 131 } 132 printf(ERROR_PREFIX "mq_unlink \n"); 133 return PTS_UNRESOLVED; 134} 135 136int child_process(char *mqname, int read_pipe, int write_pipe) 137{ 138 mqd_t mqdes; 139 int rval; 140 char reply; 141 142 rval = send_receive(read_pipe, write_pipe, 0, &reply); 143 if (rval) { 144 return rval; 145 } 146 if (reply != 'a') { 147 printf(ERROR_PREFIX "send_receive: " "expected an 'a'\n"); 148 return PTS_UNRESOLVED; 149 } 150 mqdes = mq_open(mqname, O_RDWR, 0, 0); 151 if (mqdes == (mqd_t)-1) { 152 perror(ERROR_PREFIX "mq_open"); 153 return PTS_UNRESOLVED; 154 } 155 rval = send_receive(read_pipe, write_pipe, 'b', NULL); 156 157 return 0; 158} 159 160int send_receive(int read_pipe, int write_pipe, char send, char *reply) 161{ 162 ssize_t bytes; 163 164 if (send) { 165 bytes = write(write_pipe, &send, 1); 166 if (bytes == -1) { 167 perror(ERROR_PREFIX "write fd[1]"); 168 return PTS_UNRESOLVED; 169 } 170 } 171 if (reply) { 172 bytes = read(read_pipe, reply, 1); 173 if (bytes == -1) { 174 perror(ERROR_PREFIX "read fd[0]"); 175 return PTS_UNRESOLVED; 176 } else if (bytes == 0) { 177 printf(ERROR_PREFIX "read: EOF \n"); 178 return PTS_UNRESOLVED; 179 } 180 } 181 return 0; 182} 183