error: Invalid argument; while sending msgsnd() message; not matching queue ID

2.4k views Asked by At

I was just learning IPC on linux and come up with three simple programs. One is made to create (and administrate in the feature) the message queue. The second should just send the message to the queue created by the first one. The third program is receiving data from the queue.

All programs are inheriting from the same root directory and spiting in to separate directories per source and binaries.

So lets just focus on creating and sending part, and that shall help me fix the third program as well.

add queue main.c:

#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include <sys/ipc.h>
#include <sys/msg.h>

#define FAILED -1


int main(int argc, char *argv[]) {
  // message data
  key_t key;
  int msgqid;

  if ((key = ftok("../src/main.c", 'Z')) == FAILED) {
    perror("ftok");
    exit(1);
  }

  if ((msgqid = msgget(key, 0666 | IPC_CREAT)) == FAILED) { /* create an message queue with owner & group & others permission set to rw- */
    perror("msgget");
    exit(1);
  }

  printf("Message Queue %i with key %i, been created [press return to delete]", msgqid, key);
  getchar();

  if (msgctl(msgqid, IPC_RMID, NULL) == FAILED) {
    perror("msgctl");
    exit(1);
  }
  printf("I'm outta here! \n");

  return 0;
}

send main.c:

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

#include "../../lib/shared_msgbuf.h" /* mbuf, MSGSZ */

#define FAILED -1


int main(void) {
  char s[MSGSZ];

  printf("Enter a message: ");

  if (fgets(s, sizeof s, stdin) == NULL)
    perror("fgets");
  else 
    strcpy(mbuf.mtext, s);

  printf("Connecting to the queue... \n", s);

  // Setup
  key_t key;
  int msgqid;

  if ((key = ftok("../../adqueue/src/main.c", 'Z')) == FAILED) {
    perror("ftok");
    exit(1);
  }

  if (msgqid = msgget(key, 0666) == FAILED) {
    perror("msget");
    exit(1);
  }

  printf("\n*CONNECTION ESTABLISHED* \n");
  printf("queue id: %i \n", msgqid);
  printf("queue key: %d \n", key);
  printf("message: %s \n", s);

  printf("Sending the message... \n");
  if (msgsnd(msgqid, &mbuf, MSGSZ, 0) == FAILED) {
    perror("msgsnd");
    exit(0);
  }

  return 0;
}

So the problem is that I'm getting Invalid argument error number when trying to send the message. Looking at the data, I can't get why the id is not matching since connection to the queue seems to work...

Exemplar data:

./cadqueue 
Message Queue 327680 with key 1510081535, been created [press return to delete]

./send 
Enter a message: test
Connecting to the queue... 

*CONNECTION ESTABLISHED* 
queue id: 0 
queue key: 1510081535 
message: test

Sending the message... 
msgsnd: Invalid argument
2

There are 2 answers

0
Mathieu On BEST ANSWER

Your error comes from this line:

if (msgqid = msgget(key, 0666) == FAILED) {

It should be

if ((msgqid = msgget(key, 0666)) == FAILED) {

In first case, because of operator priority, comparison (==) is done before assignation (=).

In second case, paranthesis tells compiler what must be done first.

0
user3629249 On

these are the header files needed for msgsnd()

   #include <sys/types.h>
   #include <sys/ipc.h>
   #include <sys/msg.h>

The posted code, for portability, is missing two of those header file include statements

===========

this statement:

if (msgqid = msgget(key, 0666) == FAILED) {

is missing the the IPC_CREAT that should be part of the 0666 parameter

===========

the mbuf has two fields, the mtype field, which MUST be positive, > 0 and the mtext field.

The posted code is setting the mtext field, but failing to set the mtype field.

=============

this statement:

printf("Connecting to the queue... \n", s);

has the problem that there is a input parameter, but their is no format specifier in the 'format string'

============

The key value must be the same for every access to the same message queue.

so the calls to ftok() must all have the same parameter, otherwise they will generate different/unique message queues via the call to msgget()

============

Note: message queues do not 'go away' just because a program exits. Therefore, the controlling program (or the last user of the last message) should be calling msgctl() to remove the message queue