Ilian Zapryanov
Ilian Zapryanov

Reputation: 1158

Linux ipc msgsnd() fails

I am writing a program using unix message queues. The problem is this, the program reports me "Error: 22: invalid arguments". I`ve brpwsed, but it does not satisfy my search. Here is the simple code:

    bool msg::send(int key, void* data)
{
    (void) data;
    bool res = false;
    m_msgId = msgget(key, m_mask);
    if (m_msgId == -1) {
        // noone create it
        if ((m_msgId = msgget(key, m_mask | IPC_CREAT)) == -1) {
            fprintf(stderr, "Error creating message: %d:(%s)\n",
                                            errno,
                                            strerror(errno));
            return res;
        }
    }

    union {
       msg m;
       char c[sizeof(msg)];
    } u = {*this}; // it`s a deep copy

    // here the program fails //
    int ret = msgsnd(m_msgId, u.c,
                     sizeof(msg), IPC_NOWAIT);
    if (ret == -1) {
        if (errno != EAGAIN) {
           // here is errno 22 //
            fprintf(stderr, "Error creating message: %d:(%s)\n",
                                            errno,
                                            strerror(errno));

            return res;

        } else {
            if (msgsnd(m_msgId, u.c,
                       sizeof(msg), 0) == -1) {
                fprintf(stderr, "Error creating message: %d:(%s)\n",
                                                errno,
                                                strerror(errno));
                res = false;
            }
        }
    }
    res = true;
    return res;
}

If I try to send a normal string like "1234567" it`s OK. But this buffer sending fails. What I am doing wrong? Thanks.

Upvotes: 1

Views: 1118

Answers (1)

pilcrow
pilcrow

Reputation: 58569

One EINVAL condition for msgsnd is that "the value of mtype is less than 1".

msgsnd expects that the send buffer is a long describing message type (mtype) followed by the message itself. You erroneously don't set message type, and thus msgsnd will interpret the first long-length bytes of your message as the mtype. This happens to work when the message is "1234567" but fails with *this.

You want to define something like this:

struct mymsg {
  long mtype;
  char mtext[SUFFICIENTLY_LARGE];
};

and copy your message to the memory in mtext while explicitly setting mtype >= 1.

Upvotes: 2

Related Questions