Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to open message queue in linux with huge number of elements?

According to documentation, /proc/sys/fs/mqueue/msg_max can be used in order to increase the limit of messages in the queue. The documentation also says, that the limit should not exceed HARD_MSGMAX, which is 65,536 since Linux 3.5.

However, trying to open queue even with 500 elements fails with EMFILE:

#include <stdio.h>
#include <mqueue.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <stddef.h>
#include <sys/stat.h>

int main(int argc, char** argv)
{
    int message_size = argc > 1 ? atoi(argv[1]) : 16;
    int queue_size = argc > 2 ? atoi(argv[2]) : 10000;

    printf("Trying to open queue with msgsize: %d, and maxmsg: %d\n", message_size, queue_size);

    struct mq_attr initial_attributes = (struct mq_attr){
            .mq_msgsize = message_size,
            .mq_maxmsg = queue_size
    }; 

    int open_flags = O_RDWR | O_CREAT | O_EXCL;
    int permissions = S_IWUSR | S_IRUSR;

    const char* name = "/message_queue_name;";
    mqd_t queue = mq_open(name, open_flags, permissions, &initial_attributes);

    if(queue == -1)
    {
        printf("Cannot open message queue\n");
        printf("Errno: %d [%s]\n", errno, strerror(errno));
        return 1;
    }
    else
    {
        printf("Queue has been opened successfully. Closing...\n");
        mq_close(queue);
        mq_unlink(name);
    }

    return 0;
}

Tests:

$ cat /proc/sys/fs/mqueue/msg_max
65536

$ ./main 16 300
Trying to open queue with msgsize: 16, and maxmsg: 300
Queue has been opened successfully. Closing...

$ ./main 16 500
Trying to open queue with msgsize: 16, and maxmsg: 500
Cannot open message queue
Errno: 24 [Too many open files]

According to documentation, EMFILE error code means, that process already has the maximum number of files and message queues open, though this program does not open any other files.

So, my question is: how to open message queue with huge number of elements?


UPD [1]

This is my system limits:

$ ulimit -a
-t: cpu time (seconds)              unlimited
-f: file size (blocks)              unlimited
-d: data seg size (kbytes)          unlimited
-s: stack size (kbytes)             8192
-c: core file size (blocks)         0
-m: resident set size (kbytes)      unlimited
-u: processes                       62820
-n: file descriptors                1024
-l: locked-in-memory size (kbytes)  unlimited
-v: address space (kbytes)          unlimited
-x: file locks                      unlimited
-i: pending signals                 62820
-q: bytes in POSIX msg queues       819200
-e: max nice                        30
-r: max rt priority                 99
-N 15:                              unlimited
like image 714
awesoon Avatar asked Sep 24 '15 08:09

awesoon


1 Answers

You have encountered RLIMIT_MSGQUEUE limit, see mq_overview(7):

Resource limit

The RLIMIT_MSGQUEUE resource limit, which places a limit on the amount of space that can be consumed by all of the message queues belonging to a process's real user ID, is described in getrlimit(2).

Increase it before calling mq_open(), e.g. like this:

...
#include <sys/resource.h>

int main(int argc, char** argv)
{
    struct rlimit rlim;
    rlim.rlim_cur = RLIM_INFINITY;
    rlim.rlim_max = RLIM_INFINITY;

    if (setrlimit(RLIMIT_MSGQUEUE, &rlim) == -1) {
        perror("setrlimit");
        return 1;
    }

    ...

You need root privileges for that (or CAP_SYS_RESOURCE capability, I guess).


Linux kernel really returns EMFILE for this case, check it here:

if (u->mq_bytes + mq_bytes < u->mq_bytes ||
    u->mq_bytes + mq_bytes > rlimit(RLIMIT_MSGQUEUE)) {
        spin_unlock(&mq_lock);
        /* mqueue_evict_inode() releases info->messages */
        ret = -EMFILE;
        goto out_inode;
}

The reason for EMFILE here is probably that it's the most close error code from those specified in POSIX; EMFILE is the only error code that reflects reaching a per-process limitation.

POSIX doesn't specify a more precise error code for RLIMIT_MSGQUEUE because it is Linux-specific.

like image 162
gavv Avatar answered Nov 15 '22 07:11

gavv