I'm using POSIX queues (mqueue) to communicate between threads.
The problem I have is that mq_notify doesn't function as expected in my unit tests on Cygwin. It never triggers even though the msg queue goes from empty to 1 msg.
I made an example that functions on Linux. When the same code is compiled in Cygwin, it doesn't work.
Could it be that Cygwin doesn't support mq_notify or is it a bug in Cygwin?
notification example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include "mqueue.h"
static void error(const char *msg)
{
perror(msg);
exit(1);
}
static void handleMessage(union sigval sv)
{
ssize_t n;
char buf[256];
struct mq_attr mqAttr = {0};
mqd_t mqdes = *((mqd_t *) sv.sival_ptr);
printf("handleMessage\n");
if (mq_getattr(mqdes, &mqAttr) == -1) {
error("mq_getattr");
}
printf("handleMessage msgs:%i\n", mqAttr.mq_curmsgs);
while (mqAttr.mq_curmsgs > 0) {
n = mq_receive(mqdes, buf, mqAttr.mq_msgsize, NULL);
if (n == -1) {
error("mq_receive");
break;
} else {
printf("Read %ld bytes from MQ\n", (long) n);
}
if (mq_getattr(mqdes, &mqAttr) == -1) {
error("mq_getattr");
}
}
{
struct sigevent sev;
sev.sigev_notify = SIGEV_THREAD;
sev.sigev_notify_function = handleMessage;
sev.sigev_notify_attributes = NULL;
sev.sigev_value.sival_ptr = &mqdes;
if (mq_notify(mqdes, &sev) == -1) {
error("mq_notify");
}
}
}
int main(int argc, char *argv[])
{
struct mq_attr mqAttr;
mqd_t queue;
struct sigevent sev;
mqAttr.mq_maxmsg = 10;
mqAttr.mq_msgsize = 50;
mqAttr.mq_flags = 0;
queue = mq_open(argv[1], O_CREAT | O_RDWR, 0666, NULL);
if(queue == -1) {
error("mq_open");
}
sev.sigev_notify = SIGEV_THREAD;
sev.sigev_notify_function = handleMessage;
sev.sigev_notify_attributes = NULL;
sev.sigev_value.sival_ptr = &queue;
if (mq_notify(queue, &sev) == -1) {
error("mq_notify");
}
while(1) {
/* Pass data to mq */
char buffer[20];
static int cnt = 0;
sprintf(buffer, "mq_send %i", ++cnt);
printf("%s q:%X\n", buffer, queue);
if (mq_send(queue, (char*)buffer, (strlen(buffer) + 1), 100) != 0) {
error("mq_send");
}
usleep(1000000); // sleep 1s
}
return 0;
}