Why is there a error "Cannot Allocate Memory" while creating message queue in POSIX?

10,624

Solution 1

Adrian's answer is correct, but since this is a frustratingly common error to run into on Linux when first attempting to use POSIX message queues for anything non-trivial, I thought I'd add some helpful particulars.

First, to understand the RLIMIT_MSGQUEUE resource limit, see the formula at man setrlimit:

RLIMIT_MSGQUEUE (Since Linux 2.6.8) Specifies the limit on the number of bytes that can be allocated for POSIX message queues for the real user ID of the calling process. This limit is enforced for mq_open(3). Each message queue that the user creates counts (until it is removed) against this limit according to the formula:

bytes = attr.mq_maxmsg * sizeof(struct msg_msg *) +
        attr.mq_maxmsg * attr.mq_msgsize

where attr is the mq_attr structure specified as the fourth argument to mq_open(3). The first addend in the formula, which includes sizeof(struct msg_msg *) (4 bytes on Linux/i386), ensures that the user cannot create an unlimited number of zero-length messages (such messages nevertheless each consume some system memory for bookkeeping overhead).

Given the default MQ settings (mq_maxmsg = 10, mq_msgsize = 8192) on Linux, the above formula works out to only about 10 message queues for the default limit of 819200 bytes. Hence why you will run into this problem as soon as you e.g. forget to close and unlink a couple of queues once done with them.

To raise the RLIMIT_MSGQUEUE resource limit to the maximum allowed for the user, you can use something like the following in your application's startup code:

#ifdef __linux__
    // Attempt to raise the resource limits for POSIX message queues to
    // the current hard limit enforced for the current real user ID:
    struct rlimit rlim = {RLIM_INFINITY, RLIM_INFINITY};
    const int rc = getrlimit(RLIMIT_MSGQUEUE, &rlim);
    if (rc == 0 && rlim.rlim_cur != rlim.rlim_max) {
      rlim.rlim_cur = rlim.rlim_max;
      setrlimit(RLIMIT_MSGQUEUE, &rlim);
    }
#endif

If you also ensure that you set the mq_maxmsg and mq_msgsize attributes to lower values when opening a queue (see man mq_open), you may be able to get away with a couple of hundred queues even within the constraints of the default RLIMIT_MSGQUEUE hard limit. Depending on your particular use case, of course.

Adjusting the RLIMIT_MSGQUEUE hard limit is not difficult if you have root access to the system. Once you've figured out what the limit ought to be, adjust the system-wide settings in /etc/security/limits.conf. For example, to set a hard and soft limit of 4 megabytes for the www-data user group, and no limitation for the superuser, you'd add the following lines to the file:

@www-data   -   msgqueue    4194304
root        -   msgqueue    unlimited

Solution 2

The most likely cause is that you've asked for a message queue bigger than the allowed space. The system limits are controlled in /proc/sys/fs/mqueue/. There is also a per user limit (RLIMIT_MSGQUEUE) which controls the total number of bytes that a single user can allocate. To check settings on your system, look at the value of ulimit -q, which defaults to 819200 bytes.

The developers consider message queues as suitable for small, low-latency messages. It's difficult to distribute an application that uses larger message queues, as system administration changes are required to lift the limits.

Share:
10,624
erogol
Author by

erogol

Mozilla TTS - https://github.com/mozilla/TTS

Updated on June 19, 2022

Comments

  • erogol
    erogol almost 2 years

    Why is there a error "Cannot Allocate Memory" while creating message queue in POSIX?