blob: bcdd66f2fb085a763cfa12bfbae4c8f368fde77f [file] [log] [blame]
/*
* 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 <signal.h>
#include <stdio.h>
#include <errno.h>
#include <mqueue.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#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;
}