mq_receive: message too long

26,711

Solution 1

It seems like you need to read the docs more carefully. When you call mq_receive you should pass size of the destination buffer. This size must be greater than the mq_msgsize attribute of the queue. In addition, it seems like you have an error in queue attributes initialisation that makes proper mq_receive call impossible. Here is standard message queue session:

  1. Fill mq_attr struct (doc):

    struct mq_attr attr;  
    attr.mq_flags = 0;  
    attr.mq_maxmsg = 10;  
    attr.mq_msgsize = 33;  
    attr.mq_curmsgs = 0;  
    
  2. Create queue with mq_open in master process (doc):

    mqd_t queue = mq_open(qname, O_CREAT|O_RDWR, 0644, &attr);
    
  3. In writer process open queue for writing:

    mqd_t queue = mq_open(qname, O_WRONLY);
    

    And send some text. Length of the text must be lesser than mq_msgsize attribute of the queue (doc):

    mq_send(queue, "some message", strlen("some message")+1, 1);
    
  4. In reader process open queue for reading:

    mqd_t queue = mq_open(qname, O_RDONLY);
    

    And then allocate buffer and receive message. Size of buffer *must be greater than the mq_msgsize attribute of the queue. Here we create 50-byte buffer while mq_msgsize == 33 (doc):

    char rcvmsg[50];
    int iret = mq_receive(queue, rcvmsg, 50, NULL);
    

Also remember that you should use %ld for print long instead of %d.

Solution 2

When debugging realtime POSIX queues, you should start with a sample program which works and go forward from there. Once you have the sample program running, it should be a simple matter of ensuring that your own code follows all the steps.

The following program has been tested successfully under Ubuntu 11.04:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <mqueue.h>

#define MQNAME "/pax"
#define MQMESG "Hello there!"

static mqd_t serverUp (void) {
    int rc;
    mqd_t svrHndl;
    struct mq_attr mqAttr;

    printf ("Bringing up server.\n");
    rc = mq_unlink (MQNAME);
    if (rc < 0) {
        printf ("   Warning %d (%s) on server mq_unlink.\n",
            errno, strerror (errno));
    }

    mqAttr.mq_maxmsg = 10;
    mqAttr.mq_msgsize = 1024;
    svrHndl = mq_open (MQNAME, O_RDWR|O_CREAT, S_IWUSR|S_IRUSR, &mqAttr);
    if (svrHndl < 0) {
        printf ("   Error %d (%s) on server mq_open.\n",
            errno, strerror (errno));
        exit (1);
    }
    printf ("   Server opened mqd_t of %d.\n", svrHndl);
    return svrHndl;
}

static void serverReceive (mqd_t svrHndl) {
    int rc;
    char buffer[2048];
    printf ("Server receiving on mqd_t %d.\n", svrHndl);
    rc = mq_receive (svrHndl, buffer, sizeof (buffer), NULL);
    if (rc < 0) {
        printf ("   Error %d (%s) on server mq_receive.\n",
            errno, strerror (errno));
        exit (1);
    }
    printf ("   Received [%s].\n", buffer);
}

static void serverDown (mqd_t svrHndl) {
    printf ("Bringing down server with mqd_t %d.\n", svrHndl);
    mq_close (svrHndl);
}
static void clientSend (void) {
    mqd_t cliHndl;
    int rc;
    printf ("Client sending.\n");
    cliHndl = mq_open (MQNAME, O_RDWR);
    if (cliHndl < 0) {
        printf ("   Error %d (%s) on client mq_open.\n",
            errno, strerror (errno));
        exit (1);
    }
    printf ("   Client opened mqd_t of %d.\n", cliHndl);

    rc = mq_send (cliHndl, MQMESG, sizeof (MQMESG), 1);
    if (rc < 0) {
        printf ("   Error %d (%s) on client mq_send.\n",
            errno, strerror (errno));
        exit (1);
    }

    mq_close (cliHndl);
}

int main (void) {
    mqd_t svrHndl;

    svrHndl = serverUp ();
    clientSend ();
    serverReceive (svrHndl);
    serverDown (svrHndl);

    return 0;
}

The output on my system is:

Bringing up server.
   Server opened mqd_t of 3.
Client sending.
   Client opened mqd_t of 4.
Server receiving on mqd_t 3.
   Received [Hello there!].
Bringing down server with mqd_t 3.

Solution 3

Don't forget to unlink the message queue before running your program again. If you dont unlink it, it will still use the old message queue settings. This happens when you end your program with Ctrl+C. I think it is a good idea to put the following code at the beginning of the program:

if(mq_unlink(QUEUENAME) == 0)
  fprintf(stdout, "Message queue %s removed from system.\n", QUEUENAME);

An alternative form (C++ style) that checks for real errors (like permissions) and ignores the cases where the queue already exists or not:

int rc = mq_unlink(name.c_str());
if (rc != 0 && errno != ENOENT)
      THROW_ERRNO_EXCEPTION();  

// ENOENT is the status code if the queue doesn't exist, which is not an error
// if you are immediately going to create it.
Share:
26,711

Related videos on Youtube

Madrugada
Author by

Madrugada

Updated on April 02, 2020

Comments

  • Madrugada
    Madrugada about 4 years

    I am implementing a communication between 2 processes using a queue. The problem is that when I call the function mq_receive, I get this error: Message too long.

    I have done the following:

    struct mq_attr attr;
    
    long size = attr.mq_msgsize;
    .... // initializing the queue "/gateway"
    
    int rc = mq_receive(gateway, buffer, size, &prio);
    

    If I print the size value, I get size=1, while when I print the same size but from another program (got by the same mechanism), I get something not long integer ( -1217186280 )...

    How can I solve this error?....so while size = 1, I believe it's right to say "message too long" but why is 1?

    P.S. I have also tried to put :

    int rc = mq_receive(gateway, buffer, sizeof(buffer), &prio);
    

    but with no result.

    • Duck
      Duck about 13 years
      Are you calling mq_getattr() in there somewhere to get the actual size? Otherwise you are referencing whatever junk happens to be in memory at the location of the struct.
    • Duck
      Duck about 13 years
      Post the code where you create the queue and try to read from it.
  • sg7
    sg7 over 5 years
    +1 for complete program and ` rc = mq_unlink (MQNAME);` before the open! OS may remember the old mq_msgsize. Just opening queue with new mq_msgsize is not enough.

Related