Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

mq_receive: message too long

Tags:

posix

queue

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.

like image 826
Madrugada Avatar asked Apr 11 '11 18:04

Madrugada


3 Answers

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.
like image 118
Mubin Icyer Avatar answered Nov 20 '22 23:11

Mubin Icyer


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.
like image 36
paxdiablo Avatar answered Nov 20 '22 22:11

paxdiablo


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.

like image 22
Kirill Avatar answered Nov 20 '22 22:11

Kirill