Search code examples
cpthreadsposixmessage-queue

Posix Message Queue Receive/Send/Open not working?


I want to send and receive messages with two thread-to-thread queues. But I can not create a queue either. The child works when I create a prosess. I can send and read messages between the main process and the child process, but I could not work between the threads. Why?

Source:

#include <fcntl.h>
#include <mqueue.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include "tm_api.h"

#define QUEUE_NAME  "/testqueue"
#define MAX_SIZE    1024

static void * queue_server(void *pars);
static void * queue_client(void *parc);

static void * queue_server(void *pars) {
    mqd_t mq;
    unsigned int sender;
    int bytes_read;

    struct mq_attr attr;
    char buffer[MAX_SIZE];

    attr.mq_flags   = 0;
    attr.mq_maxmsg  = 10;
    attr.mq_msgsize = MAX_SIZE;
    attr.mq_curmsgs = 0;

    mq = mq_open(QUEUE_NAME, O_CREAT | O_RDONLY | O_NONBLOCK, 0644, &attr);
    printf("mq_receive : %d\n", mq);
    memset(buffer, 0x00, sizeof(buffer));
    mq_unlink (QUEUE_NAME);
    while(1) {

        bytes_read = mq_receive(mq, buffer, MAX_SIZE, &sender);
        if(bytes_read >= 0) {
            printf("SERVER: Received message: %s\n", buffer);
        } else {
            printf("SERVER: None \n");
        }

        fflush(stdout);
        tm_thread_sleep(1);
    }

    mq_close(mq);
    mq_unlink(QUEUE_NAME);

    return NULL;
}

static void * queue_client(void *parc) {
    mqd_t mq;
    char buffer[MAX_SIZE];

    mq = mq_open(QUEUE_NAME, O_RDWR);
    printf("mq_send : %d\n", mq);

    int count = 0;
    while(1) {
        snprintf(buffer, sizeof(buffer), "MESSAGE %d", count++);

        printf("CLIENT: Send message... \n");
        mq_send(mq, buffer, MAX_SIZE+1, 0);

        fflush(stdout);
        tm_thread_sleep(1);
    }

    mq_close(mq);
    return NULL;
}

int main() {

    pthread_t client, server;
    printf("Start...\n");
    pthread_create(&server, NULL, &queue_server, NULL);
    pthread_create(&client, NULL, &queue_client, NULL);
    pthread_join(server, NULL);
    pthread_join(client, NULL);
    printf("Done...\n");
    return (EXIT_SUCCESS);
}

Output :

Start... 

mq_receive :3

SERVER: None

mq_send : -1

CLIENT: Send message...

SERVER: None

CLIENT: Send message...

SERVER: None

Solution

  • The problem here is, You are sending more than the size of buffer.

        mq_send(mq, buffer, MAX_SIZE+1, 0);
    

    it should be

        mq_send(mq, buffer, MAX_SIZE, 0);
    

    You could have figured it out if you have verified return value of mq_send. It was returning

    define EMSGSIZE 90 /* Message too long */ error.

    After modification I was able to get the following output.

    Start...
    mq_send : 4
    mq_receive : 3
    CLIENT: Send message...
    SERVER: Received message: MESSAGE 0
    CLIENT: Send message...
    SERVER: Received message: MESSAGE 1
    CLIENT: Send message...
    SERVER: Received message: MESSAGE 2
    CLIENT: Send message...
    SERVER: Received message: MESSAGE 3
    

    Find the complete code as below.

    #include <fcntl.h>
    #include <mqueue.h>
    #include <pthread.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/stat.h>
    #include <unistd.h>
    #include <errno.h>
    
    #define QUEUE_NAME  "/testqueue"
    #define MAX_SIZE    1024
    
    static void * queue_server(void *pars);
    static void * queue_client(void *parc);
    
    static void * queue_server(void *pars) {
    mqd_t mq;
    unsigned int sender;
    int bytes_read;
    
    struct mq_attr attr;
    char buffer[MAX_SIZE];
    
    attr.mq_flags = 0;
    attr.mq_maxmsg = 10;
    attr.mq_msgsize = MAX_SIZE;
    attr.mq_curmsgs = 0;
    
    mq = mq_open(QUEUE_NAME, O_RDONLY | O_NONBLOCK | O_CREAT, 0666, &attr);
    printf("mq_receive : %d\n",mq);
            printf("SERVER: None %d %d \n", errno, bytes_read);
    memset(buffer, 0x00, sizeof(buffer));
    mq_unlink (QUEUE_NAME);
    while(1) {
    
        bytes_read = mq_receive(mq, buffer, MAX_SIZE, &sender);
        if(bytes_read >= 0) {
            printf("SERVER: Received message: %s\n", buffer);
        } else {
            printf("SERVER: None %d %d \n", errno, bytes_read);
        }
    
      //  fflush(stdout);
        sleep(1);
        }
    mq_close(mq);
    mq_unlink(QUEUE_NAME);
    
    return NULL;
    }
    static void * queue_client(void *parc) {
    mqd_t mq;
    char buffer[MAX_SIZE];
    
    
    struct mq_attr attr;
    
    attr.mq_flags = 0;
    attr.mq_maxmsg = 10;
    attr.mq_msgsize = MAX_SIZE;
    attr.mq_curmsgs = 0;
    
    
    
    mq = mq_open(QUEUE_NAME, O_CREAT|O_WRONLY|O_NONBLOCK , 0666,&attr);
    printf("mq_send : %d\n",mq);
    
    int count = 0;
    while(1) {
        snprintf(buffer, sizeof(buffer), "MESSAGE %d", count++);
    
        printf("CLIENT: Send message... \n");
        int bytes_read = mq_send(mq, buffer, MAX_SIZE, 0);
            printf("CLIENT: send %d %d \n", errno, bytes_read);
    
    //    fflush(stdout);
        sleep(1);
    }
    mq_close(mq);
    return NULL;
    }
    
    int main() {
    
    pthread_t client, server;
    printf("Start...\n");
    pthread_create(&server, NULL, &queue_server, NULL);
    pthread_create(&client, NULL, &queue_client, NULL);
    pthread_join(server, NULL);
    pthread_join(client, NULL);
    printf("Done...\n");
    return (EXIT_SUCCESS);
    }