1/* 2 * Copyright (c) 2003, Intel Corporation. All rights reserved. 3 * Created by: julie.n.fleischer 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 * Test that tests to check if O_CREAT and O_EXCL are set that no other 11 * message queue exists are atomic. 12 * 13 * Test case will just attempt to call mq_open() with O_CREAT and O_EXCL 14 * using the same name in two different processes. If one process fails, 15 * the test is considered a pass. 16 * 17 * This is a best attempt to test that these are atomic. It does make the 18 * assumption (which could generally be untrue) that both mq_open() calls 19 * will attempt to be made at the same time. For the sake of this test case, 20 * this is fine (will have some false positives, but no false negatives). 21 */ 22 23#include <sys/mman.h> 24#include <sys/stat.h> 25#include <sys/types.h> 26#include <sys/wait.h> 27#include <errno.h> 28#include <fcntl.h> 29#include <mqueue.h> 30#include <signal.h> 31#include <stdio.h> 32#include <string.h> 33#include <unistd.h> 34#include "posixtest.h" 35 36#define NAMESIZE 50 37#define TNAME "mq_open/16-1.c" 38 39int main(void) 40{ 41 char qname[NAMESIZE]; 42 char fname[NAMESIZE]; 43 int pid, succeeded = 0; 44 int fd; 45 void *pa = NULL; 46 mqd_t childqueue, queue; 47 48 /* 49 * initialize both queues 50 */ 51 childqueue = (mqd_t) - 1; 52 queue = (mqd_t) - 1; 53 54 sprintf(qname, "/mq_open_16-1_%d", getpid()); 55 56 sprintf(fname, "/tmp/pts_mq_open_16_1_%d", getpid()); 57 unlink(fname); 58 fd = open(fname, O_CREAT | O_RDWR | O_EXCL, S_IRUSR | S_IWUSR); 59 if (fd == -1) { 60 printf(TNAME " Error at open(): %s\n", strerror(errno)); 61 return PTS_UNRESOLVED; 62 } 63 /* file is empty now, will cause "Bus error" */ 64 write(fd, fname, sizeof(int)); 65 unlink(fname); 66 67 pa = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 68 if (pa == MAP_FAILED) { 69 printf(TNAME " Error at mmap: %s\n", strerror(errno)); 70 close(fd); 71 return PTS_FAIL; 72 } 73 *(int *)pa = 0; 74 75 pid = fork(); 76 if (pid == 0) { 77 sigset_t mask; 78 int sig; 79 80 /* child here */ 81 82 /* try to sync with parent for mq_open */ 83 sigemptyset(&mask); 84 sigaddset(&mask, SIGUSR1); 85 sigprocmask(SIG_BLOCK, &mask, NULL); 86 sigwait(&mask, &sig); 87 88 childqueue = mq_open(qname, O_CREAT | O_EXCL | O_RDWR, 89 S_IRUSR | S_IWUSR, NULL); 90 if (childqueue != (mqd_t) - 1) { 91 ++*(int *)pa; 92#ifdef DEBUG 93 printf("mq_open() in child succeeded\n"); 94 } else { 95 printf("mq_open() in child failed\n"); 96#endif 97 } 98 } else { 99 /* parent here */ 100 int i; 101 102 sleep(1); 103 kill(pid, SIGUSR1); 104 105 queue = mq_open(qname, O_CREAT | O_EXCL | O_RDWR, 106 S_IRUSR | S_IWUSR, NULL); 107 if (queue != (mqd_t) - 1) { 108 ++*(int *)pa; 109#ifdef DEBUG 110 printf("mq_open() in parent succeeded\n"); 111 } else { 112 printf("mq_open() in parent failed\n"); 113#endif 114 } 115 116 if (wait(&i) == -1) { 117 perror("Error waiting for child to exit"); 118 printf("Test UNRESOLVED\n"); 119 mq_close(queue); 120 mq_close(childqueue); 121 mq_unlink(qname); 122 close(fd); 123 munmap(pa, sizeof(int)); 124 return PTS_UNRESOLVED; 125 } 126 127 mq_close(queue); 128 mq_close(childqueue); 129 mq_unlink(qname); 130 131 succeeded = *(int *)pa; 132 close(fd); 133 munmap(pa, sizeof(int)); 134 135 if (succeeded == 0) { 136 printf("Test FAILED - mq_open() never succeeded\n"); 137 return PTS_FAIL; 138 } 139 140 if (succeeded > 1) { 141 printf("Test FAILED - mq_open() succeeded twice\n"); 142 return PTS_FAIL; 143 } 144 145 printf("Test PASSED\n"); 146 return PTS_PASS; 147 } 148 149 return PTS_UNRESOLVED; 150} 151