1
2 #include <sys/types.h>
3 #include <sys/event.h>
4 #include <sys/select.h>
5 #include <sys/wait.h>
6 #include <err.h>
7 #include <fcntl.h>
8 #include <mqueue.h>
9 #include <signal.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <unistd.h>
13
14 #define MQNAME "/mytstqueue5"
15 #define LOOPS 1000
16 #define PRIO 10
17
18 static void
sighandler(int sig __unused)19 sighandler(int sig __unused)
20 {
21 write(1, "timeout\n", 8);
22 _exit(1);
23 }
24
25 int
main(void)26 main(void)
27 {
28 int status;
29 struct mq_attr attr;
30 struct sigaction sa;
31 sigset_t set;
32 siginfo_t info;
33 mqd_t mq;
34 pid_t pid;
35
36 mq_unlink(MQNAME);
37
38 sigemptyset(&set);
39 sigaddset(&set, SIGRTMIN);
40 sigprocmask(SIG_BLOCK, &set, NULL);
41 sigemptyset(&sa.sa_mask);
42 sa.sa_flags = SA_SIGINFO;
43 sa.sa_sigaction = (void *) SIG_DFL;
44 sigaction(SIGRTMIN, &sa, NULL);
45
46 attr.mq_maxmsg = 5;
47 attr.mq_msgsize = 128;
48 mq = mq_open(MQNAME, O_CREAT | O_RDWR | O_EXCL, 0666, &attr);
49 if (mq == (mqd_t)-1)
50 err(1, "mq_open()");
51 status = mq_getattr(mq, &attr);
52 if (status)
53 err(1, "mq_getattr()");
54 pid = fork();
55 if (pid == 0) { /* child */
56 int prio, j, i;
57 char *buf;
58 struct sigevent sigev;
59
60 signal(SIGALRM, sighandler);
61
62 sigev.sigev_notify = SIGEV_SIGNAL;
63 sigev.sigev_signo = SIGRTMIN;
64 sigev.sigev_value.sival_int = 2;
65
66 mq_close(mq);
67 mq = mq_open(MQNAME, O_RDWR | O_NONBLOCK);
68 if (mq == (mqd_t)-1)
69 err(1, "child: mq_open");
70 buf = malloc(attr.mq_msgsize);
71 for (j = 0; j < LOOPS; ++j) {
72 alarm(3);
73 status = mq_notify(mq, &sigev);
74 if (status)
75 err(1, "child: mq_notify");
76 status = sigwaitinfo(&set, &info);
77 if (status == -1)
78 err(1, "child: sigwaitinfo");
79 if (info.si_value.sival_int != 2)
80 err(1, "child: sival_int");
81 status = mq_receive(mq, buf, attr.mq_msgsize, &prio);
82 if (status == -1)
83 err(2, "child: mq_receive");
84 for (i = 0; i < attr.mq_msgsize; ++i)
85 if (buf[i] != i)
86 err(3, "child: message data corrupted");
87 if (prio != PRIO)
88 err(4, "child: priority is incorrect: %d",
89 prio);
90 }
91 alarm(0);
92 free(buf);
93 mq_close(mq);
94 return (0);
95 } else if (pid == -1) {
96 err(1, "fork()");
97 } else {
98 char *buf;
99 int i, j;
100
101 signal(SIGALRM, sighandler);
102 buf = malloc(attr.mq_msgsize);
103 for (j = 0; j < LOOPS; ++j) {
104 for (i = 0; i < attr.mq_msgsize; ++i) {
105 buf[i] = i;
106 }
107 alarm(3);
108 status = mq_send(mq, buf, attr.mq_msgsize, PRIO);
109 if (status) {
110 kill(pid, SIGKILL);
111 err(2, "mq_send()");
112 }
113 }
114 alarm(3);
115 wait(&status);
116 alarm(0);
117 }
118 status = mq_close(mq);
119 if (status)
120 err(1, "mq_close");
121 mq_unlink(MQNAME);
122 return (0);
123 }
124