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 if the message queue is full and O_NONBLOCK is not set, 11 * mq_timedsend() will block until abs_timeout is reached. 12 * 13 * Test by sending messages in a child process until the message queue is full. 14 * At this point, the child should be blocking on sending. Then, have the 15 * parent wait for the timeout and return pass when the next message is sent 16 * to the message queue. 17 */ 18 19#include <stdio.h> 20#include <mqueue.h> 21#include <fcntl.h> 22#include <sys/stat.h> 23#include <sys/types.h> 24#include <sys/wait.h> 25#include <time.h> 26#include <unistd.h> 27#include <string.h> 28#include <stdlib.h> 29#include <stdint.h> 30#include <signal.h> 31#include <errno.h> 32#include "posixtest.h" 33 34#define NAMESIZE 50 35#define MSGSTR "0123456789" 36#define BUFFER 40 37#define MAXMSG 5 38 39#define TIMEOUT 7 40 41#define CHILDPASS 1 42#define CHILDFAIL 0 43 44char gqname[NAMESIZE]; 45mqd_t gqueue; 46 47/* 48 * This handler is just used to catch the signal and stop sleep (so the 49 * parent knows the child is still busy sending signals). 50 */ 51void stopsleep_handler(int signo) 52{ 53 return; 54} 55 56int main() 57{ 58 int pid; 59 struct mq_attr attr; 60 const char *msgptr = MSGSTR; 61 62 sprintf(gqname, "/mq_timedsend_5-3_%d", getpid()); 63 64 attr.mq_maxmsg = MAXMSG; 65 attr.mq_msgsize = BUFFER; 66 gqueue = mq_open(gqname, O_CREAT |O_RDWR, S_IRUSR | S_IWUSR, &attr); 67 if (gqueue == (mqd_t)-1) { 68 perror("mq_open() did not return success"); 69 return PTS_UNRESOLVED; 70 } 71 72 if ((pid = fork()) == 0) { 73 /* child here */ 74 int i, sig; 75 struct timespec ts; 76 sigset_t mask; 77 78 /* wait for parent to set up handler */ 79 sigemptyset(&mask); 80 sigaddset(&mask, SIGUSR1); 81 sigprocmask(SIG_BLOCK,&mask,NULL); 82 sigwait(&mask, &sig); 83 84 /* child should block in < TIMEOUT seconds */ 85 ts.tv_sec=time(NULL)+TIMEOUT; 86 ts.tv_nsec=0; 87 88 for (i=0; i<MAXMSG+1; i++) { 89 if (mq_timedsend(gqueue, msgptr, 90 strlen(msgptr), 1, &ts) != 0) { 91 /* send will fail after timeout occurs*/ 92 kill(getppid(), SIGABRT); 93 return CHILDPASS; 94 } 95 /* send signal to parent each time message is sent */ 96 kill(getppid(), SIGABRT); 97 } 98 printf("Child never interrupted\n"); 99 return CHILDFAIL; 100 } else { 101 /* parent here */ 102 struct sigaction act; 103 int j; 104 105 /* parent runs stopsleep_handler when sleep is interrupted 106 by child */ 107 act.sa_handler=stopsleep_handler; 108 act.sa_flags=0; 109 sigemptyset(&act.sa_mask); 110 sigaction(SIGABRT, &act, 0); 111 112 /* wait 1 second and tell child handler is set up */ 113 sleep(1); 114 kill(pid, SIGUSR1); 115 116 /* wait for heartbeats from child */ 117 for (j=0; j<MAXMSG+1; j++) { 118 if (sleep(3) == 0) { 119 /* If sleep finished, child is probably blocking */ 120 break; 121 } 122 } 123 124 if (j == MAXMSG+1) { 125 printf("Child never blocked\n"); 126 printf("Test FAILED\n"); 127 kill(pid, SIGKILL); //kill child 128 mq_close(gqueue); 129 mq_unlink(gqname); 130 return PTS_FAIL; 131 } 132 133 /* 134 * Wait for timeout to complete. 135 */ 136 if (sleep(TIMEOUT) == 0) { 137 /* 138 * If sleep lasted the full time, child never timed out 139 */ 140 printf("Child never timed out\n"); 141 kill(pid, SIGKILL); //kill child 142 mq_close(gqueue); 143 mq_unlink(gqname); 144 printf("Test FAILED\n"); 145 return PTS_FAIL; 146 } 147 148 mq_close(gqueue); 149 mq_unlink(gqname); 150 printf("Test PASSED\n"); 151 return PTS_PASS; 152 } 153 154 return PTS_UNRESOLVED; 155} 156 157