4
votes

My Environment:

  • CentOS 6.5 (64bit kernel)
  • gcc 4.4.7 20120313

I am trying to set attribute for POSIX message queue, but the code does not change the attribute. I only get default attribute values.

Could you point out what the problem is with my code?

I execute the a.out as an user (not root).

#include <stdio.h>
#include <mqueue.h> // for message queue
#include <sys/stat.h>
#include <stdlib.h> // for EXIT_FAILURE
#include <string.h>

/*
gcc [file] -lrt
*/

static void showAttr(mqd_t mqd)
{
    struct mq_attr attr;

    mq_getattr(mqd, &attr);

    printf("maxmsg = %d\n", attr.mq_maxmsg);
    printf("msgsize = %d\n", attr.mq_msgsize);
    printf("curmsgs = %d\n", attr.mq_curmsgs);

}

int main()
{
    mqd_t mqd;
    int flags;
    int ret;
    struct mq_attr attr;

    flags = O_RDWR | O_CREAT;

    attr.mq_flags = 0; // or O_NONBLOCK
    attr.mq_maxmsg = 60;
    attr.mq_msgsize = 120;
    attr.mq_curmsgs = 0;

    // POSIX IPC name should start with "/"
    mqd = mq_open("/mq", flags,
//      (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH),
        0644,
        &attr );

    if (mqd < 0) {
        printf("open failed\n");
        exit(EXIT_FAILURE);
    }
    printf("open ok\n");

    sleep(1);

    showAttr(mqd);

    ret = mq_close(mqd);
    if (ret != 0) {
        printf("open failed\n");
        exit(EXIT_FAILURE);     
    }
    printf("close ok\n");

    return 0;
}

I found that following code works. However, when I try to set attr.mq_maxmsg (=60), the mq_open fails.

#include <stdio.h>
#include <mqueue.h> // for message queue
#include <sys/stat.h>
#include <stdlib.h> // for EXIT_FAILURE
#include <string.h>
#include <errno.h>

/*
gcc [file] -lrt
*/

static void showAttr(mqd_t mqd)
{
    struct mq_attr attr;

    mq_getattr(mqd, &attr);

    printf("maxmsg = %d\n", attr.mq_maxmsg);
    printf("msgsize = %d\n", attr.mq_msgsize);
    printf("curmsgs = %d\n", attr.mq_curmsgs);

}

int main()
{
    mqd_t mqd;
    int flags;
    int ret;
    struct mq_attr attr;

    flags = O_RDWR | O_CREAT;

    // POSIX IPC name should start with "/"

    // 1. once open without attribute setting
    mqd = mq_open("/mq", flags,
        (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) );
    mq_getattr(mqd, &attr);
    mq_unlink("/mq");
    mq_close(mqd);

    // 2. set values of attribute
    // attr.mq_maxmsg = 10;
    attr.mq_msgsize = 120;

    // 3. allocate attribute
    mqd = mq_open("/mq", flags,
        (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH),
    //   0644,
        &attr );

    if (mqd < 0) {
        printf("open failed %d\n", mqd);
        exit(EXIT_FAILURE);
    }
    printf("open ok\n");

    sleep(1);

    showAttr(mqd);


    ret = mq_close(mqd);
    if (ret != 0) {
        printf("open failed\n");
        exit(EXIT_FAILURE);     
    }
    printf("close ok\n");

    return 0;
}
2
Mentioning that setting values higher than max allowed caused the failure and pointing to where max values are defined was a huge help. Many thanks.Rake36

2 Answers

3
votes

The following code works.

I used mq_unlink() before mq_open() as pilcrow suggested.

And, the other source of the problem was I set attr.mq_maxmsg greather than 10 (which is defined in /proc/sys/fs/mqueue/msg_max ). If I set attr.mq_maxmsg less than and equal to 10, these is no problem for setting attribute.

#include <stdio.h>
#include <mqueue.h> // for message queue
#include <sys/stat.h>
#include <stdlib.h> // for EXIT_FAILURE
#include <string.h>
#include <errno.h>

/*
gcc [file] -lrt
*/

static void showAttr(mqd_t mqd)
{
    struct mq_attr attr;

    mq_getattr(mqd, &attr);

    printf("maxmsg = %d\n", attr.mq_maxmsg);
    printf("msgsize = %d\n", attr.mq_msgsize);
    printf("curmsgs = %d\n", attr.mq_curmsgs);

}

int main()
{
    mqd_t mqd;
    int flags;
    int ret;
    struct mq_attr attr;

    flags = O_RDWR | O_CREAT;

    mq_unlink("/mq");

    attr.mq_flags = 0;
    attr.mq_maxmsg = 3; // ***
    attr.mq_msgsize = 141;
    attr.mq_curmsgs = 0;

    mqd = mq_open("/mq", flags,
        (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH),
        &attr );

    if (mqd < 0) {
        printf("open failed %d\n", mqd);
        exit(EXIT_FAILURE);
    }
    printf("open ok\n");

    sleep(1);

    showAttr(mqd);


    ret = mq_close(mqd);
    if (ret != 0) {
        printf("open failed\n");
        exit(EXIT_FAILURE);     
    }
    printf("close ok\n");

    return 0;
}
1
votes

mq_open() is returning an already existing queue whose attributes were set at the time it was created. The O_CREAT flag thus has no effect, and the attributes you specify are ignored as well.

Call mq_unlink() before your open, and perhaps set O_EXCL as well, and see the difference.