/* * Copyright (c) 2003, Intel Corporation. All rights reserved. * Created by: crystal.xiong REMOVE-THIS AT intel DOT com * This file is licensed under the GPL license. For the full content * of this license, see the COPYING file at the top level of this * source tree. */ /* * mq_unlink() test plan: * If one or more process have the message queue open, destruction of the * message queue will be postponed until all reference to the message queue * have been closed. At this time, call to mq_open() with O_CREAT flag may fail * until the message queue is actually removed. * Steps: * 1. Create 2 pipes to communicate with parent and child processes. * 2. Parent uses mq_open to create a new mq and tell child to open it using pipe. * 3. Child open the mq and tell parent, so mq has 2 reference now. * 4. Parent want to mq_unlink the mq, since Child does not close the mq, * mq_unlink will postpone. At this time, if using mq_open to create * a new mq with the same name, mq_open may fail. * * 3/27/2003 Fixed a bug pointed by Krzysztof Benedyczak and * Gregoire Pichon. mq_open may fail in this case. Not * must fail. */ #include #include #include #include #include #include #include #include #include "posixtest.h" #define PIPE_READ 0 #define PIPE_WRITE 1 #define TEST "2-1" #define FUNCTION "mq_unlink" #define ERROR_PREFIX "unexpected error: " FUNCTION " " TEST ": " #define NAMESIZE 50 int parent_process(char *mqname, int read_pipe, int write_pipe, int child_pid); int child_process(char *mqname, int read_pipe, int write_pipe); int send_receive(int read_pipe, int write_pipe, char send, char *reply); int main() { char mqname[NAMESIZE]; pid_t pid; int to_parent[2]; int to_child[2]; int rval; struct sigaction sa; sa.sa_handler = SIG_IGN; sa.sa_flags = 0; sigemptyset(&sa.sa_mask); sigaction(SIGCHLD, &sa, NULL); sprintf(mqname, "/" FUNCTION "_" TEST "_%d", getpid()); rval = pipe(to_parent); if (rval == -1) { perror(ERROR_PREFIX "fd[0]"); return PTS_UNRESOLVED; } rval = pipe(to_child); if (rval == -1) { perror(ERROR_PREFIX "fd[1]"); return PTS_UNRESOLVED; } pid = fork(); if (pid == -1) { perror(ERROR_PREFIX "fork"); return PTS_UNRESOLVED; } if (pid == 0) { //child process close(to_parent[PIPE_READ]); close(to_child[PIPE_WRITE]); return child_process(mqname, to_child[PIPE_READ], to_parent[PIPE_WRITE]); } else { //parent process close(to_parent[PIPE_WRITE]); close(to_child[PIPE_READ]); return parent_process(mqname, to_parent[PIPE_READ], to_child[PIPE_WRITE], pid); } } int parent_process(char *mqname, int read_pipe, int write_pipe, int child_pid) { mqd_t mqdes; char reply; int rval; mqdes = mq_open(mqname, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR, 0); if (mqdes == (mqd_t)-1) { perror(ERROR_PREFIX "mq_open"); return PTS_UNRESOLVED; } // Tell child a message queue has been opened. rval = send_receive(read_pipe, write_pipe, 'a', &reply); if (rval) { return rval; } if (reply != 'b') { printf(ERROR_PREFIX "send_receive: " "expected a 'b'"); return PTS_UNRESOLVED; } if (mq_unlink(mqname) == 0) { if (mq_open(mqname, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR, 0) == -1) { 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"); printf("Test PASSED\n"); return PTS_PASS; } else { if (mq_unlink(mqname) != 0) { printf(ERROR_PREFIX "mq_unlink(2)"); return PTS_UNRESOLVED; } 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"); printf("Test PASSED\n"); return PTS_PASS; } } printf(ERROR_PREFIX "mq_unlink \n"); return PTS_UNRESOLVED; } int child_process(char *mqname, int read_pipe, int write_pipe) { mqd_t mqdes; int rval; char reply; rval = send_receive(read_pipe, write_pipe, 0, &reply); if (rval) { return rval; } if (reply != 'a') { printf(ERROR_PREFIX "send_receive: " "expected an 'a'\n"); return PTS_UNRESOLVED; } mqdes = mq_open(mqname, O_RDWR, 0, 0); if (mqdes == (mqd_t)-1) { perror(ERROR_PREFIX "mq_open"); return PTS_UNRESOLVED; } rval = send_receive(read_pipe, write_pipe, 'b', NULL); return 0; } int send_receive(int read_pipe, int write_pipe, char send, char *reply) { ssize_t bytes; if (send) { bytes = write(write_pipe, &send, 1); if (bytes == -1) { perror(ERROR_PREFIX "write fd[1]"); return PTS_UNRESOLVED; } } if (reply) { bytes = read(read_pipe, reply, 1); if (bytes == -1) { perror(ERROR_PREFIX "read fd[0]"); return PTS_UNRESOLVED; } else if (bytes == 0) { printf(ERROR_PREFIX "read: EOF \n"); return PTS_UNRESOLVED; } } return 0; }